summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/Makefile.am2
-rw-r--r--runtime/Makefile.in281
-rw-r--r--runtime/atomic.h12
-rw-r--r--runtime/cfsysline.c12
-rw-r--r--runtime/conf.c9
-rw-r--r--runtime/datetime.c109
-rw-r--r--runtime/datetime.h9
-rw-r--r--runtime/debug.c21
-rw-r--r--runtime/glbl.c147
-rw-r--r--runtime/glbl.h3
-rw-r--r--runtime/janitor.c101
-rw-r--r--runtime/janitor.h35
-rw-r--r--runtime/librsgt.c1
-rw-r--r--runtime/librsgt_read.c4
-rw-r--r--runtime/module-template.h74
-rw-r--r--runtime/modules.c57
-rw-r--r--runtime/modules.h3
-rw-r--r--runtime/msg.c339
-rw-r--r--runtime/msg.h8
-rw-r--r--runtime/net.c36
-rw-r--r--runtime/nsd_gtls.c7
-rw-r--r--runtime/parser.c168
-rw-r--r--runtime/parser.h2
-rw-r--r--runtime/prop.c17
-rw-r--r--runtime/queue.c31
-rw-r--r--runtime/queue.h16
-rw-r--r--runtime/ratelimit.c3
-rw-r--r--runtime/rsconf.c65
-rw-r--r--runtime/rsyslog.h3
-rw-r--r--runtime/ruleset.c13
-rw-r--r--runtime/statsobj.h2
-rw-r--r--runtime/stringbuf.c9
-rw-r--r--runtime/stringbuf.h2
-rw-r--r--runtime/syslogd-types.h11
-rw-r--r--runtime/typedefs.h1
-rw-r--r--runtime/wti.h6
36 files changed, 1242 insertions, 377 deletions
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 5585b32..a100938 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -25,6 +25,8 @@ librsyslog_la_SOURCES = \
unlimited_select.h \
conf.c \
conf.h \
+ janitor.c \
+ janitor.h \
rsconf.c \
rsconf.h \
parser.h \
diff --git a/runtime/Makefile.in b/runtime/Makefile.in
index 4223dc4..79862c3 100644
--- a/runtime/Makefile.in
+++ b/runtime/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -16,51 +17,6 @@
VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -116,8 +72,7 @@ sbin_PROGRAMS =
@ENABLE_GUARDTIME_TRUE@am__append_7 = librsgt.la
@ENABLE_GUARDTIME_TRUE@am__append_8 = lmsig_gt.la
subdir = runtime
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(top_srcdir)/depcomp
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/atomic_operations.m4 \
$(top_srcdir)/m4/atomic_operations_64bit.m4 \
@@ -167,7 +122,6 @@ 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 =
librsgt_la_LIBADD =
am__librsgt_la_SOURCES_DIST = librsgt.c librsgt_read.c librsgt.h
@@ -182,15 +136,16 @@ librsyslog_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
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-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-debug.lo \
- librsyslog_la-obj.lo librsyslog_la-modules.lo \
- librsyslog_la-statsobj.lo librsyslog_la-stream.lo \
- librsyslog_la-var.lo librsyslog_la-wtp.lo librsyslog_la-wti.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-debug.lo librsyslog_la-obj.lo \
+ librsyslog_la-modules.lo librsyslog_la-statsobj.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 \
@@ -291,18 +246,6 @@ lmzlibw_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(lmzlibw_la_LDFLAGS) $(LDFLAGS) -o $@
@ENABLE_ZLIB_TRUE@am_lmzlibw_la_rpath = -rpath $(pkglibdir)
PROGRAMS = $(sbin_PROGRAMS)
-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__depfiles_maybe = depfiles
@@ -315,16 +258,20 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(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 =
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
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 =
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(libgcry_la_SOURCES) $(librsgt_la_SOURCES) \
$(librsyslog_la_SOURCES) $(lmcry_gcry_la_SOURCES) \
$(lmnet_la_SOURCES) $(lmnetstrms_la_SOURCES) \
@@ -341,28 +288,6 @@ DIST_SOURCES = $(am__libgcry_la_SOURCES_DIST) \
$(am__lmsig_gt_la_SOURCES_DIST) \
$(am__lmstrmsrv_la_SOURCES_DIST) \
$(am__lmzlibw_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
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -581,6 +506,8 @@ librsyslog_la_SOURCES = \
unlimited_select.h \
conf.c \
conf.h \
+ janitor.c \
+ janitor.h \
rsconf.c \
rsconf.h \
parser.h \
@@ -754,17 +681,15 @@ $(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}; \
- }
-
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
@$(NORMAL_INSTALL)
+ test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)"
@list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
@@ -772,8 +697,6 @@ install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
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)"; \
}
@@ -789,18 +712,14 @@ uninstall-pkglibLTLIBRARIES:
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}; \
- }
-
+ @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
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)
-
librsgt.la: $(librsgt_la_OBJECTS) $(librsgt_la_DEPENDENCIES) $(EXTRA_librsgt_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(am_librsgt_la_rpath) $(librsgt_la_OBJECTS) $(librsgt_la_LIBADD) $(LIBS)
../$(am__dirstamp):
@@ -819,51 +738,36 @@ librsgt.la: $(librsgt_la_OBJECTS) $(librsgt_la_DEPENDENCIES) $(EXTRA_librsgt_la_
../$(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)
-
lmnet.la: $(lmnet_la_OBJECTS) $(lmnet_la_DEPENDENCIES) $(EXTRA_lmnet_la_DEPENDENCIES)
$(AM_V_CCLD)$(lmnet_la_LINK) $(am_lmnet_la_rpath) $(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_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_gt.la: $(lmsig_gt_la_OBJECTS) $(lmsig_gt_la_DEPENDENCIES) $(EXTRA_lmsig_gt_la_DEPENDENCIES)
$(AM_V_CCLD)$(lmsig_gt_la_LINK) $(am_lmsig_gt_la_rpath) $(lmsig_gt_la_OBJECTS) $(lmsig_gt_la_LIBADD) $(LIBS)
-
lmstrmsrv.la: $(lmstrmsrv_la_OBJECTS) $(lmstrmsrv_la_DEPENDENCIES) $(EXTRA_lmstrmsrv_la_DEPENDENCIES)
$(AM_V_CCLD)$(lmstrmsrv_la_LINK) $(am_lmstrmsrv_la_rpath) $(lmstrmsrv_la_OBJECTS) $(lmstrmsrv_la_LIBADD) $(LIBS)
-
lmzlibw.la: $(lmzlibw_la_OBJECTS) $(lmzlibw_la_DEPENDENCIES) $(EXTRA_lmzlibw_la_DEPENDENCIES)
$(AM_V_CCLD)$(lmzlibw_la_LINK) $(am_lmzlibw_la_rpath) $(lmzlibw_la_OBJECTS) $(lmzlibw_la_LIBADD) $(LIBS)
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
+ test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
@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; \
+ 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|.*|.|' \
+ 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 } \
@@ -884,8 +788,7 @@ uninstall-sbinPROGRAMS:
@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)/' \
- `; \
+ -e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
@@ -901,8 +804,16 @@ clean-sbinPROGRAMS:
mostlyclean-compile:
-rm -f *.$(OBJEXT)
- -rm -f ../*.$(OBJEXT)
- -rm -f ../*.lo
+ -rm -f ../librsyslog_la-action.$(OBJEXT)
+ -rm -f ../librsyslog_la-action.lo
+ -rm -f ../librsyslog_la-outchannel.$(OBJEXT)
+ -rm -f ../librsyslog_la-outchannel.lo
+ -rm -f ../librsyslog_la-parse.$(OBJEXT)
+ -rm -f ../librsyslog_la-parse.lo
+ -rm -f ../librsyslog_la-template.$(OBJEXT)
+ -rm -f ../librsyslog_la-template.lo
+ -rm -f ../librsyslog_la-threads.$(OBJEXT)
+ -rm -f ../librsyslog_la-threads.lo
distclean-compile:
-rm -f *.tab.c
@@ -925,6 +836,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-glbl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-hashtable.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-janitor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-linkedlist.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-lookup.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-modules.Plo@am__quote@
@@ -1030,6 +942,13 @@ librsyslog_la-conf.lo: conf.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@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
@@ -1373,15 +1292,26 @@ 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)
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
- $(am__define_uniq_tagged_files); \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
@@ -1393,11 +1323,15 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$$unique; \
fi; \
fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
@@ -1406,21 +1340,6 @@ 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
@@ -1567,21 +1486,21 @@ uninstall-am: uninstall-pkglibLTLIBRARIES uninstall-sbinPROGRAMS
.MAKE: install-am install-strip
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool 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 \
+ clean-sbinPROGRAMS ctags 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
+ tags uninstall uninstall-am uninstall-pkglibLTLIBRARIES \
+ uninstall-sbinPROGRAMS
update-systemd:
diff --git a/runtime/atomic.h b/runtime/atomic.h
index 2a89558..49c17d8 100644
--- a/runtime/atomic.h
+++ b/runtime/atomic.h
@@ -181,18 +181,18 @@
(*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 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)
#endif
/* we need to handle 64bit atomics seperately as some platforms have
- * 32 bit atomics, but not 64 biot ones... -- rgerhards, 2010-12-01
+ * 32 bit atomics, but not 64 bit ones... -- rgerhards, 2010-12-01
*/
-#ifdef HAVE_ATOMIC_BUILTINS_64BIT
+#ifdef HAVE_ATOMIC_BUILTINS64
# define ATOMIC_INC_uint64(data, phlpmut) ((void) __sync_fetch_and_add(data, 1))
# define ATOMIC_DEC_unit64(data, phlpmut) ((void) __sync_sub_and_fetch(data, 1))
# define ATOMIC_INC_AND_FETCH_uint64(data, phlpmut) __sync_fetch_and_add(data, 1)
@@ -224,6 +224,6 @@
# 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_BUILTINS_64BIT */
+#endif /* #ifdef HAVE_ATOMIC_BUILTINS64 */
#endif /* #ifndef INCLUDED_ATOMIC_H */
diff --git a/runtime/cfsysline.c b/runtime/cfsysline.c
index a437b7f..2e7bd36 100644
--- a/runtime/cfsysline.c
+++ b/runtime/cfsysline.c
@@ -363,9 +363,12 @@ static rsRetVal doGetGID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *p
}
do {
+ char *p;
+
/* Increase bufsize and try again.*/
bufSize *= 2;
- CHKmalloc(stringBuf = realloc(stringBuf, bufSize));
+ CHKmalloc(p = realloc(stringBuf, bufSize));
+ stringBuf = p;
err = getgrnam_r((char*)szName, &gBuf, stringBuf, bufSize, &pgBuf);
} while((pgBuf == NULL) && (err == ERANGE));
@@ -522,15 +525,14 @@ finalize_it:
static rsRetVal doGetWord(uchar **pp, rsRetVal (*pSetHdlr)(void*, uchar*), void *pVal)
{
DEFiRet;
- cstr_t *pStrB;
+ cstr_t *pStrB = NULL;
uchar *pNewVal;
ASSERT(pp != NULL);
ASSERT(*pp != NULL);
CHKiRet(getWord(pp, &pStrB));
- CHKiRet(cstrConvSzStrAndDestruct(pStrB, &pNewVal, 0));
- pStrB = NULL;
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pNewVal, 0));
DBGPRINTF("doGetWord: get newval '%s' (len %d), hdlr %p\n",
pNewVal, (int) ustrlen(pNewVal), pSetHdlr);
@@ -915,7 +917,7 @@ DEFFUNC_llExecFunc(unregHdlrsHeadExec)
int iNumElts;
/* first find element */
- iRet = llFindAndDelete(&(pListHdr->llCmdHdlrs), pParam);
+ CHKiRet(llFindAndDelete(&(pListHdr->llCmdHdlrs), pParam));
/* now go back and check how many elements are left */
CHKiRet(llGetNumElts(&(pListHdr->llCmdHdlrs), &iNumElts));
diff --git a/runtime/conf.c b/runtime/conf.c
index 83931bc..87600ad 100644
--- a/runtime/conf.c
+++ b/runtime/conf.c
@@ -261,7 +261,7 @@ rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEn
{
uchar *p;
uchar *tplName = NULL;
- cstr_t *pStrB;
+ cstr_t *pStrB = NULL;
DEFiRet;
ASSERT(pp != NULL);
@@ -294,14 +294,17 @@ rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEn
++p;
}
CHKiRet(cstrFinalize(pStrB));
- CHKiRet(cstrConvSzStrAndDestruct(pStrB, &tplName, 0));
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &tplName, 0));
}
CHKiRet(OMSRsetEntry(pOMSR, iEntry, tplName, iTplOpts));
finalize_it:
- if(iRet != RS_RET_OK)
+ if(iRet != RS_RET_OK) {
free(tplName);
+ if(pStrB != NULL)
+ cstrDestruct(&pStrB);
+ }
*pp = p;
diff --git a/runtime/datetime.c b/runtime/datetime.c
index 3d50238..ba2ed35 100644
--- a/runtime/datetime.c
+++ b/runtime/datetime.c
@@ -5,7 +5,7 @@
* 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-2012 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2008-2014 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -363,9 +363,19 @@ finalize_it:
* 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][ 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
*/
static rsRetVal
-ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
+ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr, const int bParseTZ)
{
/* variables to temporarily hold time information while we parse */
int month;
@@ -374,6 +384,12 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
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; /* UTC offset in hours */
+ int OffsetMinute; /* UTC offset in minutes */
/* end variables to temporarily hold time information while we parse */
int lenStr;
uchar *pszTS;
@@ -386,6 +402,21 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
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:
*
@@ -407,9 +438,6 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
* 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
*/
- if(lenStr < 3)
- ABORT_FINALIZE(RS_RET_INVLD_TIME);
-
switch(*pszTS++)
{
case 'j':
@@ -558,7 +586,7 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
/* time part */
hour = srSLMGParseInt32(&pszTS, &lenStr);
- if(hour > 1970 && hour < 2100) {
+ 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
@@ -590,6 +618,41 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
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 = glblFindTimezoneInfo((char*) tzstring)) == NULL) {
+ DBGPRINTF("ParseTIMESTAMP3164: invalid TZ string '%s' -- ignored\n",
+ tzstring);
+ } else {
+ OffsetMode = tzinfo->offsMode;
+ OffsetHour = tzinfo->offsHour;
+ OffsetMinute = tzinfo->offsMin;
+ }
+ }
+ }
+
/* 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
@@ -618,8 +681,13 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
pTime->hour = hour;
pTime->minute = minute;
pTime->second = second;
- pTime->secfracPrecision = 0;
- pTime->secfrac = 0;
+ 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:
@@ -988,6 +1056,31 @@ int formatTimestampUnix(struct syslogTime *ts, char *pBuf)
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;
+}
+
+
/* queryInterface function
* rgerhards, 2008-03-05
diff --git a/runtime/datetime.h b/runtime/datetime.h
index 72c3a97..c96f7ee 100644
--- a/runtime/datetime.h
+++ b/runtime/datetime.h
@@ -34,7 +34,7 @@ typedef struct datetime_s {
BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */
void (*getCurrTime)(struct syslogTime *t, time_t *ttSeconds);
rsRetVal (*ParseTIMESTAMP3339)(struct syslogTime *pTime, uchar** ppszTS, int*);
- rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar** pszTS, int*);
+ rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar** pszTS, int*, const int bParseTZ);
int (*formatTimestampToMySQL)(struct syslogTime *ts, char* pDst);
int (*formatTimestampToPgSQL)(struct syslogTime *ts, char *pDst);
int (*formatTimestamp3339)(struct syslogTime *ts, char* pBuf);
@@ -48,7 +48,7 @@ BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */
int (*formatTimestampUnix)(struct syslogTime *ts, char*pBuf);
time_t (*syslogTime2time_t)(struct syslogTime *ts);
ENDinterface(datetime)
-#define datetimeCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */
+#define datetimeCURR_IF_VERSION 8 /* increment whenever you change the interface structure! */
/* interface changes:
* 1 - initial version
* 2 - not compatible to 1 - bugfix required ParseTIMESTAMP3164 to accept char ** as
@@ -58,10 +58,15 @@ ENDinterface(datetime)
* 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
*/
+#define PARSE3164_TZSTRING 1
+#define NO_PARSE3164_TZSTRING 0
+
/* prototypes */
PROTOTYPEObj(datetime);
void applyDfltTZ(struct syslogTime *pTime, char *tz);
+int getWeekdayNbr(struct syslogTime *ts);
#endif /* #ifndef INCLUDED_DATETIME_H */
diff --git a/runtime/debug.c b/runtime/debug.c
index c0029ff..bfdfa34 100644
--- a/runtime/debug.c
+++ b/runtime/debug.c
@@ -695,10 +695,11 @@ static dbgThrdInfo_t *dbgGetThrdInfo(void)
pthread_mutex_lock(&mutCallStack);
if((pThrd = pthread_getspecific(keyCallStack)) == NULL) {
/* construct object */
- pThrd = calloc(1, sizeof(dbgThrdInfo_t));
- pThrd->thrd = pthread_self();
- (void) pthread_setspecific(keyCallStack, pThrd);
- DLL_Add(CallStack, pThrd);
+ if((pThrd = calloc(1, sizeof(dbgThrdInfo_t))) != NULL) {
+ pThrd->thrd = pthread_self();
+ (void) pthread_setspecific(keyCallStack, pThrd);
+ DLL_Add(CallStack, pThrd);
+ }
}
pthread_mutex_unlock(&mutCallStack);
return pThrd;
@@ -738,25 +739,27 @@ static void dbgGetThrdName(char *pszBuf, size_t lenBuf, pthread_t thrd, int bInc
snprintf(pszBuf, lenBuf, "%lx", (long) thrd);
} else {
if(bIncludeNumID) {
- snprintf(pszBuf, lenBuf, "%s (%lx)", pThrd->pszThrdName, (long) thrd);
+ snprintf(pszBuf, lenBuf, "%-15s (%lx)", pThrd->pszThrdName, (long) thrd);
} else {
- snprintf(pszBuf, lenBuf, "%s", pThrd->pszThrdName);
+ snprintf(pszBuf, lenBuf, "%-15s", pThrd->pszThrdName);
}
}
-
}
/* set a name for the current thread. The caller provided string is duplicated.
+ * Note: we must lock the "dbgprint" mutex, because dbgprint() uses the thread
+ * name and we could get a race (and abort) in cases where both are executed in
+ * parallel and we free or incompletely-copy the string.
*/
void dbgSetThrdName(uchar *pszName)
{
-return;
-
+ pthread_mutex_lock(&mutdbgprint);
dbgThrdInfo_t *pThrd = dbgGetThrdInfo();
if(pThrd->pszThrdName != NULL)
free(pThrd->pszThrdName);
pThrd->pszThrdName = strdup((char*)pszName);
+ pthread_mutex_unlock(&mutdbgprint);
}
diff --git a/runtime/glbl.c b/runtime/glbl.c
index 73e986e..1867410 100644
--- a/runtime/glbl.c
+++ b/runtime/glbl.c
@@ -34,7 +34,9 @@
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
+#include <ctype.h>
#include <assert.h>
+#include <stdint.h>
#include "rsyslog.h"
#include "obj.h"
@@ -45,6 +47,7 @@
#include "atomic.h"
#include "errmsg.h"
#include "action.h"
+#include "parserif.h"
#include "rainerscript.h"
#include "net.h"
@@ -102,6 +105,7 @@ static int bSpaceLFOnRcv = 0; /* replace newlines with spaces on reception: 0 -
static int bEscape8BitChars = 0; /* escape characters > 127 on reception: 0 - no, 1 - yes */
static int bEscapeTab = 1; /* escape tab control character when doing CC escapes: 0 - no, 1 - yes */
static int bParserEscapeCCCStyle = 0; /* escape control characters in c style: 0 - no, 1 - yes */
+short janitorInterval = 10; /* interval (in minutes) at which the janitor runs */
pid_t glbl_ourpid;
#ifndef HAVE_ATOMIC_BUILTINS
@@ -112,6 +116,8 @@ static int iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask); /* si
#endif
static uchar *SourceIPofLocalClient = NULL; /* [ar] Source IP for local client to be used on multihomed host */
+tzinfo_t *tzinfos = NULL;
+static int ntzinfos;
/* tables for interfacing with the v6 config system */
static struct cnfparamdescr cnfparamdescr[] = {
@@ -136,6 +142,7 @@ static struct cnfparamdescr cnfparamdescr[] = {
{ "parser.escapecontrolcharactertab", eCmdHdlrBinary, 0},
{ "parser.escapecontrolcharacterscstyle", eCmdHdlrBinary, 0 },
{ "stdlog.channelspec", eCmdHdlrString, 0 },
+ { "janitor.interval", eCmdHdlrPositiveInt, 0 },
{ "processinternalmessages", eCmdHdlrBinary, 0 }
};
static struct cnfparamblk paramblk =
@@ -144,6 +151,16 @@ static struct cnfparamblk paramblk =
cnfparamdescr
};
+static struct cnfparamdescr timezonecnfparamdescr[] = {
+ { "id", eCmdHdlrString, 0 },
+ { "offset", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk timezonepblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(timezonecnfparamdescr)/sizeof(struct cnfparamdescr),
+ timezonecnfparamdescr
+ };
+
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
@@ -677,6 +694,120 @@ glblPrepCnf(void)
cnfparamvals = NULL;
}
+
+static void
+freeTimezoneInfo(void)
+{
+ int i;
+ for(i = 0 ; i < ntzinfos ; ++i)
+ free(tzinfos[i].id);
+ free(tzinfos);
+ tzinfos = NULL;
+}
+
+static void
+displayTzinfos(void)
+{
+ int i;
+ if(!Debug)
+ return;
+ for(i = 0 ; i < ntzinfos ; ++i)
+ dbgprintf("tzinfo: '%s':%c%2.2d:%2.2d\n",
+ tzinfos[i].id, tzinfos[i].offsMode,
+ tzinfos[i].offsHour, tzinfos[i].offsMin);
+}
+
+
+/* Note: this function is NOT thread-safe!
+ * This is currently not needed as used only during
+ * initialization.
+ */
+static inline rsRetVal
+addTimezoneInfo(uchar *tzid, char offsMode, int8_t offsHour, int8_t offsMin)
+{
+ DEFiRet;
+ tzinfo_t *newti;
+ CHKmalloc(newti = realloc(tzinfos, (ntzinfos+1)*sizeof(tzinfo_t)));
+ CHKmalloc(newti[ntzinfos].id = strdup((char*)tzid));
+ newti[ntzinfos].offsMode = offsMode;
+ newti[ntzinfos].offsHour = offsHour;
+ newti[ntzinfos].offsMin = offsMin;
+ ++ntzinfos, tzinfos = newti;
+finalize_it:
+ RETiRet;
+}
+
+
+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*
+glblFindTimezoneInfo(char *id)
+{
+ return (tzinfo_t*) bsearch(id, tzinfos, ntzinfos, sizeof(tzinfo_t), bs_arrcmp_tzinfo);
+}
+
+/* handle the timezone() object. Each incarnation adds one additional
+ * zone info to the global table of time zones.
+ */
+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);
+ 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);
+ }
+ }
+
+ 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(id, offsMode, offsHour, offsMin);
+
+done:
+ cnfparamvalsDestruct(pvals, &timezonepblk);
+ free(id);
+ free(offset);
+}
+
/* 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.
@@ -737,6 +868,14 @@ glblDestructMainqCnfObj()
mainqCnfObj = NULL;
}
+/* 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);
+}
/* This processes the "regular" parameters which are to be set after the
* config has been fully loaded.
@@ -747,6 +886,10 @@ glblDoneLoadCnf(void)
int i;
unsigned char *cstr;
+ qsort(tzinfos, ntzinfos, sizeof(tzinfo_t), qs_arrcmp_tzinfo);
+ DBGPRINTF("Timezone information table (%d entries):\n", ntzinfos);
+ displayTzinfos();
+
if(cnfparamvals == NULL)
goto finalize_it;
@@ -812,6 +955,8 @@ glblDoneLoadCnf(void)
}
}
errmsg.LogError(0, RS_RET_OK, "debug log file is '%s', fd %d", pszAltDbgFileName, altdbg);
+ } else if(!strcmp(paramblk.descr[i].name, "janitor.interval")) {
+ janitorInterval = (int) cnfparamvals[i].val.d.n;
} else {
dbgprintf("glblDoneLoadCnf: program error, non-handled "
"param '%s'\n", paramblk.descr[i].name);
@@ -822,6 +967,7 @@ glblDoneLoadCnf(void)
Debug = DEBUG_ONDEMAND;
stddbg = -1;
}
+
finalize_it: return;
}
@@ -877,6 +1023,7 @@ BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */
free(LocalHostName);
free(LocalHostNameOverride);
free(LocalFQDNName);
+ freeTimezoneInfo();
objRelease(prop, CORE_COMPONENT);
if(propLocalHostNameToDelete != NULL)
prop.Destruct(&propLocalHostNameToDelete);
diff --git a/runtime/glbl.h b/runtime/glbl.h
index 8a9f038..8afedc9 100644
--- a/runtime/glbl.h
+++ b/runtime/glbl.h
@@ -104,15 +104,18 @@ ENDinterface(glbl)
PROTOTYPEObj(glbl);
extern int glblDebugOnShutdown; /* start debug log when we are shut down */
+extern short janitorInterval;
static inline pid_t glblGetOurPid(void) { return glbl_ourpid; }
static inline void glblSetOurPid(pid_t pid) { glbl_ourpid = pid; }
void glblPrepCnf(void);
void glblProcessCnf(struct cnfobj *o);
+void glblProcessTimezone(struct cnfobj *o);
void glblProcessMainQCnf(struct cnfobj *o);
void glblDestructMainqCnfObj();
void glblDoneLoadCnf(void);
const uchar * glblGetWorkDirRaw(void);
+tzinfo_t* glblFindTimezoneInfo(char *id);
#endif /* #ifndef GLBL_H_INCLUDED */
diff --git a/runtime/janitor.c b/runtime/janitor.c
new file mode 100644
index 0000000..b4471a8
--- /dev/null
+++ b/runtime/janitor.c
@@ -0,0 +1,101 @@
+/* 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 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;
+ 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:
+ 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..2585721
--- /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/librsgt.c b/runtime/librsgt.c
index a812456..f824749 100644
--- a/runtime/librsgt.c
+++ b/runtime/librsgt.c
@@ -406,6 +406,7 @@ readStateFile(gtfile gf)
free(gf->blkStrtHash);
goto err;
}
+ close(fd);
return;
err:
diff --git a/runtime/librsgt_read.c b/runtime/librsgt_read.c
index 972b5a4..bcb0099 100644
--- a/runtime/librsgt_read.c
+++ b/runtime/librsgt_read.c
@@ -611,9 +611,9 @@ rsgt_printBLOCK_SIG(FILE *fp, block_sig_t *bs, uint8_t verbose)
fprintf(fp, "\tIV............: ");
outputHexBlob(fp, bs->iv, getIVLen(bs), verbose);
fputc('\n', fp);
- fprintf(fp, "\tRecord Count..: %llu\n", bs->recCount);
+ fprintf(fp, "\tRecord Count..: %llu\n", (long long unsigned) bs->recCount);
fprintf(fp, "\tSignature Type: %s\n", sigTypeName(bs->sigID));
- fprintf(fp, "\tSignature Len.: %u\n", bs->sig.der.len);
+ fprintf(fp, "\tSignature Len.: %u\n", (unsigned) bs->sig.der.len);
fprintf(fp, "\tSignature.....: ");
outputHexBlob(fp, bs->sig.der.data, bs->sig.der.len, verbose);
fputc('\n', fp);
diff --git a/runtime/module-template.h b/runtime/module-template.h
index 95c35b4..9fadf63 100644
--- a/runtime/module-template.h
+++ b/runtime/module-template.h
@@ -425,6 +425,44 @@ static rsRetVal newInpInst(struct nvlst *lst)\
}
+
+/* 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,
@@ -667,6 +705,24 @@ static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)())\
*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 Strgen
* modules. This can be used if no specific handling (e.g. to cover version
* differences) is needed.
@@ -1040,7 +1096,7 @@ static rsRetVal SetShutdownImmdtPtr(instanceData __attribute__((unused)) *pData,
}
-/* parse() - main entry point of parser modules
+/* parse() - main entry point of parser modules (v1 config interface)
*/
#define BEGINparse \
static rsRetVal parse(msg_t *pMsg)\
@@ -1055,6 +1111,22 @@ static rsRetVal parse(msg_t *pMsg)\
}
+/* parse2() - main entry point of parser modules (v2+ config interface)
+ */
+#define BEGINparse2 \
+static rsRetVal parse2(instanceConf_t *const pInst, msg_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.
diff --git a/runtime/modules.c b/runtime/modules.c
index ad80a7b..6c5583a 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -64,7 +64,6 @@
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
-DEFobjCurrIf(parser)
DEFobjCurrIf(strgen)
static modInfo_t *pLoadedModules = NULL; /* list of currently-loaded modules */
@@ -358,7 +357,7 @@ addModToGlblList(modInfo_t *pThis)
rsRetVal
readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast)
{
- cfgmodules_etry_t *pNew;
+ cfgmodules_etry_t *pNew = NULL;
cfgmodules_etry_t *pLast;
DEFiRet;
assert(pThis != NULL);
@@ -403,6 +402,10 @@ readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **
*ppLast = pLast;
*ppNew = pNew;
finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL)
+ free(pNew);
+ }
RETiRet;
}
@@ -555,7 +558,6 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
rsRetVal localRet;
modInfo_t *pNew = NULL;
uchar *pName;
- parser_t *pParser; /* used for parser modules */
strgen_t *pStrgen; /* used for strgen modules */
rsRetVal (*GetName)(uchar**);
rsRetVal (*modGetType)(eModType_t *pType);
@@ -641,7 +643,7 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
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.om.newActInst = NULL;
+ pNew->mod.im.newInpInst = NULL;
} else if(localRet != RS_RET_OK) {
ABORT_FINALIZE(localRet);
}
@@ -732,31 +734,25 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
case eMOD_LIB:
break;
case eMOD_PARSER:
- /* first, we need to obtain the parser 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(parser, CORE_COMPONENT));
- /* here, we create a new parser object */
- CHKiRet((*pNew->modQueryEtryPt)((uchar*)"parse", &pNew->mod.pm.parse));
+ 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(parser.Construct(&pParser));
-
- /* check some features */
- localRet = pNew->isCompatibleWithFeature(sFEATUREAutomaticSanitazion);
- if(localRet == RS_RET_OK){
- CHKiRet(parser.SetDoSanitazion(pParser, RSTRUE));
- }
- localRet = pNew->isCompatibleWithFeature(sFEATUREAutomaticPRIParsing);
- if(localRet == RS_RET_OK){
- CHKiRet(parser.SetDoPRIParsing(pParser, RSTRUE));
- }
-
- CHKiRet(parser.SetName(pParser, pName));
- CHKiRet(parser.SetModPtr(pParser, pNew));
- CHKiRet(parser.ConstructFinalize(pParser));
+ CHKiRet(parserConstructViaModAndName(pNew, pName, NULL));
break;
case eMOD_STRGEN:
/* first, we need to obtain the strgen object. We could not do that during
@@ -765,7 +761,6 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
* handles that.
*/
CHKiRet(objUse(strgen, CORE_COMPONENT));
- /* here, we create a new parser object */
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"strgen", &pNew->mod.sm.strgen));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"GetName", &GetName));
CHKiRet(GetName(&pName));
@@ -1130,7 +1125,7 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
free(pPathBuf);
/* we always alloc enough memory for everything we potentiall need to add */
lenPathBuf = PATHBUF_OVERHEAD;
- CHKmalloc(pPathBuf = malloc(sizeof(char)*lenPathBuf));
+ CHKmalloc(pPathBuf = malloc(sizeof(uchar)*lenPathBuf));
}
*pPathBuf = '\0'; /* we do not need to append the path - its already in the module name */
iPathLen = 0;
@@ -1153,7 +1148,7 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
free(pPathBuf);
/* we always alloc enough memory for everything we potentiall need to add */
lenPathBuf = iPathLen + PATHBUF_OVERHEAD;
- CHKmalloc(pPathBuf = malloc(sizeof(char)*lenPathBuf));
+ CHKmalloc(pPathBuf = malloc(sizeof(uchar)*lenPathBuf));
}
memcpy((char *) pPathBuf, (char *)pModDirCurr, iPathLen);
@@ -1177,7 +1172,6 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
* algo over time... -- rgerhards, 2008-03-05
*/
strncat((char *) pPathBuf, ".so", lenPathBuf - strlen((char*) pPathBuf) - 1);
- iPathLen += 3;
}
/* complete load path constructed, so ... GO! */
@@ -1373,7 +1367,6 @@ BEGINObjClassExit(module, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MA
CODESTARTObjClassExit(module)
/* release objects we no longer need */
objRelease(errmsg, CORE_COMPONENT);
- objRelease(parser, CORE_COMPONENT);
free(pModDir);
# ifdef DEBUG
modUsrPrintAll(); /* debug aid - TODO: integrate with debug.c, at least the settings! */
diff --git a/runtime/modules.h b/runtime/modules.h
index c3a9c9e..634d298 100644
--- a/runtime/modules.h
+++ b/runtime/modules.h
@@ -148,6 +148,9 @@ struct modInfo_s {
char dummy;
} lm;
struct { /* data for parser modules */
+ rsRetVal (*newParserInst)(struct nvlst *lst, void *pinst);
+ rsRetVal (*freeParserInst)(void *pinst);
+ rsRetVal (*parse2)(instanceConf_t *const, msg_t*);
rsRetVal (*parse)(msg_t*);
} pm;
struct { /* data for strgen modules */
diff --git a/runtime/msg.c b/runtime/msg.c
index ded8cfe..66c3b7b 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -82,6 +82,8 @@ DEFobjCurrIf(prop)
DEFobjCurrIf(net)
DEFobjCurrIf(var)
+static char *one_digit[10] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
static char *two_digits[100] = {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
@@ -94,6 +96,32 @@ static char *two_digits[100] = {
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99"};
+static char *wdayNames[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+
+/* 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 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;
short lenName;
@@ -505,6 +533,8 @@ propNameToID(uchar *pName, propid_t *pPropID)
*pPropID = PROP_PROCID;
} else if(!strcmp((char*) pName, "msgid")) {
*pPropID = PROP_MSGID;
+ } else if(!strcmp((char*) pName, "jsonmesg")) {
+ *pPropID = PROP_JSONMESG;
} else if(!strcmp((char*) pName, "parsesuccess")) {
*pPropID = PROP_PARSESUCCESS;
#ifdef USE_LIBUUID
@@ -600,6 +630,8 @@ uchar *propIDToName(propid_t propID)
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");
case PROP_SYS_NOW:
@@ -1600,6 +1632,31 @@ getTimeReported(msg_t * const pM, enum tplFormatTypes eFmt)
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 == '+')? "+" : "-";
}
ENDfunc
return "INVALID eFmt OPTION!";
@@ -1686,6 +1743,31 @@ static char *getTimeGenerated(msg_t * const pM, enum tplFormatTypes eFmt)
MsgUnlock(pM);
}
return(pM->pszRcvdAt_SecFrac);
+ case tplFmtWDayName:
+ return wdayNames[getWeekdayNbr(&pM->tRcvdAt)];
+ case tplFmtWDay:
+ return one_digit[getWeekdayNbr(&pM->tRcvdAt)];
+ case tplFmtMonth:
+ return two_digits[(int)pM->tRcvdAt.month];
+ case tplFmtYear:
+ if(pM->tRcvdAt.year >= 1967 && pM->tRcvdAt.year <= 2099)
+ return years[pM->tRcvdAt.year - 1967];
+ else
+ return "YEAR OUT OF RANGE(1967-2099)";
+ case tplFmtDay:
+ return two_digits[(int)pM->tRcvdAt.day];
+ case tplFmtHour:
+ return two_digits[(int)pM->tRcvdAt.hour];
+ case tplFmtMinute:
+ return two_digits[(int)pM->tRcvdAt.minute];
+ case tplFmtSecond:
+ return two_digits[(int)pM->tRcvdAt.second];
+ case tplFmtTZOffsHour:
+ return two_digits[(int)pM->tRcvdAt.OffsetHour];
+ case tplFmtTZOffsMin:
+ return two_digits[(int)pM->tRcvdAt.OffsetMinute];
+ case tplFmtTZOffsDirection:
+ return (pM->tRcvdAt.OffsetMode == '+')? "+" : "-";
}
ENDfunc
return "INVALID eFmt OPTION!";
@@ -1929,6 +2011,95 @@ void MsgSetParseSuccess(msg_t * const pMsg, int bSuccess)
pMsg->bParseSuccess = bSuccess;
}
+
+/* return full message as a json string */
+const uchar*
+msgGetJSONMESG(msg_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);
+ 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, "$!", 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(msg_t * const pMsg, ruleset_t *pRuleset)
@@ -2322,7 +2493,7 @@ finalize_it:
* we need it. The rest of the code already knows how to handle an
* unset HOSTNAME.
*/
-void MsgSetHOSTNAME(msg_t *pThis, uchar* pszHOSTNAME, int lenHOSTNAME)
+void MsgSetHOSTNAME(msg_t *pThis, const uchar* pszHOSTNAME, const int lenHOSTNAME)
{
assert(pThis != NULL);
@@ -2373,7 +2544,7 @@ void MsgSetMSGoffs(msg_t * const pMsg, short offs)
* the caller is responsible for freeing it.
* rgerhards, 2009-06-23
*/
-rsRetVal MsgReplaceMSG(msg_t *pThis, uchar* pszMSG, int lenMSG)
+rsRetVal MsgReplaceMSG(msg_t *pThis, const uchar* pszMSG, int lenMSG)
{
int lenNew;
uchar *bufNew;
@@ -2406,12 +2577,14 @@ finalize_it:
* terminated by '\0'.
* rgerhards, 2009-06-16
*/
-void MsgSetRawMsg(msg_t *pThis, char* pszRawMsg, size_t lenMsg)
+void MsgSetRawMsg(msg_t *pThis, const char* pszRawMsg, size_t lenMsg)
{
+ int deltaSize;
assert(pThis != NULL);
if(pThis->pszRawMsg != pThis->szRawMsg)
free(pThis->pszRawMsg);
+ deltaSize = lenMsg - pThis->iLenRawMsg;
pThis->iLenRawMsg = lenMsg;
if(pThis->iLenRawMsg < CONF_RAWMSG_BUFSIZE) {
/* small enough: use fixed buffer (faster!) */
@@ -2424,6 +2597,11 @@ void MsgSetRawMsg(msg_t *pThis, char* pszRawMsg, size_t lenMsg)
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;
}
@@ -2638,7 +2816,8 @@ jsonAddVal(uchar *pSrc, unsigned buflen, es_str_t **dst, int escapeAll)
for(i = 0 ; i < buflen ; ++i) {
c = pSrc[i];
- if( (c >= 0x23 && c <= 0x5b)
+ if( (c >= 0x23 && c <= 0x2e)
+ || (c >= 0x30 && c <= 0x5b)
|| (c >= 0x5d /* && c <= 0x10FFFF*/)
|| c == 0x20 || c == 0x21) {
/* no need to escape */
@@ -2947,6 +3126,10 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
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);
@@ -3024,8 +3207,6 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
break;
case PROP_CEE_ALL_JSON:
if(pMsg->json == NULL) {
- if(*pbMustBeFreed == 1)
- free(pRes);
pRes = (uchar*) "{}";
bufLen = 2;
*pbMustBeFreed = 0;
@@ -3040,8 +3221,6 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
getJSONPropVal(pMsg, pProp, &pRes, &bufLen, pbMustBeFreed);
break;
case PROP_SYS_BOM:
- if(*pbMustBeFreed == 1)
- free(pRes);
pRes = (uchar*) "\xEF\xBB\xBF";
*pbMustBeFreed = 0;
break;
@@ -3058,18 +3237,18 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
{
struct timespec tp;
- if(*pbMustBeFreed == 1)
- free(pRes);
if((pRes = (uchar*) MALLOC(sizeof(uchar) * 32)) == NULL) {
RET_OUT_OF_MEMORY;
}
- *pbMustBeFreed = 1;
if(clock_gettime(CLOCK_UPTIME, &tp) == -1) {
+ free(pRes);
*pPropLen = sizeof("**SYSCALL FAILED**") - 1;
return(UCHAR_CONSTANT("**SYSCALL FAILED**"));
}
+ *pbMustBeFreed = 1;
+
snprintf((char*) pRes, sizeof(uchar) * 32, "%ld", tp.tv_sec);
}
@@ -3078,18 +3257,18 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
{
struct sysinfo s_info;
- if(*pbMustBeFreed == 1)
- free(pRes);
if((pRes = (uchar*) MALLOC(sizeof(uchar) * 32)) == NULL) {
RET_OUT_OF_MEMORY;
}
- *pbMustBeFreed = 1;
if(sysinfo(&s_info) < 0) {
+ free(pRes);
*pPropLen = sizeof("**SYSCALL FAILED**") - 1;
return(UCHAR_CONSTANT("**SYSCALL FAILED**"));
}
+ *pbMustBeFreed = 1;
+
snprintf((char*) pRes, sizeof(uchar) * 32, "%ld", s_info.uptime);
}
# endif
@@ -3157,7 +3336,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
/* 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) * sizeof(char));
+ pBufStart = pBuf = MALLOC((iLen + 1) * sizeof(uchar));
if(pBuf == NULL) {
if(*pbMustBeFreed == 1)
free(pRes);
@@ -3335,7 +3514,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
if(iTo > bufLen) /* iTo is very large, if no to-position is set in the template! */
iTo = bufLen;
iLen = iTo - iFrom + 1; /* the +1 is for an actual char, NOT \0! */
- pBufStart = pBuf = MALLOC((iLen + 1) * sizeof(char));
+ pBufStart = pBuf = MALLOC((iLen + 1) * sizeof(uchar));
if(pBuf == NULL) {
if(*pbMustBeFreed == 1)
free(pRes);
@@ -3389,7 +3568,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
uchar *pBStart;
uchar *pB;
uchar *pSrc;
- pBStart = pB = MALLOC((bufLen + 1) * sizeof(char));
+ pBStart = pB = MALLOC((bufLen + 1) * sizeof(uchar));
if(pB == NULL) {
if(*pbMustBeFreed == 1)
free(pRes);
@@ -3795,6 +3974,132 @@ finalize_it:
#undef isProp
+/* Set a single property based on the JSON object provided. The
+ * property name is extracted from the JSON object.
+ */
+static rsRetVal
+msgSetPropViaJSON(msg_t *__restrict__ const pMsg, const char *name, struct json_object *json)
+{
+ const char *psz;
+ int val;
+ prop_t *propFromHost = NULL;
+ prop_t *propRcvFromIP = NULL;
+ DEFiRet;
+
+ // TODO: think if we need to lock the message mutex. For some updates
+ // we probably need to!
+
+ /* 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, "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, 0, &propFromHost);
+ } else if(!strcmp(name, "fromhost-ip")) {
+ psz = json_object_get_string(json);
+ MsgSetRcvFromIPStr(pMsg, (const uchar*)psz, strlen(psz), &propRcvFromIP);
+ } else if(!strcmp(name, "$!")) {
+ msgAddJSON(pMsg, (uchar*)"!", json);
+ } else {
+ /* we ignore unknown properties */
+ DBGPRINTF("msgSetPropViaJSON: unkonwn property ignored: %s\n",
+ name);
+ }
+ 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(msg_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_errors[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_PARSE_ERR);
+ }
+
+ json_object_object_foreach(json, name, val) {
+ msgSetPropViaJSON(pMsg, name, val);
+ }
+ json_object_put(json);
+
+finalize_it:
+ if(tokener != NULL)
+ json_tokener_free(tokener);
+ RETiRet;
+}
+
+
/* get the severity - this is an entry point that
* satisfies the base object class getSeverity semantics.
* rgerhards, 2008-01-14
diff --git a/runtime/msg.h b/runtime/msg.h
index 2d3e995..ec22545 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -177,12 +177,12 @@ void MsgSetRcvFrom(msg_t *pMsg, prop_t*);
void MsgSetRcvFromStr(msg_t *const pMsg, const uchar* pszRcvFrom, const int, prop_t **);
rsRetVal MsgSetRcvFromIP(msg_t *pMsg, prop_t*);
rsRetVal MsgSetRcvFromIPStr(msg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp);
-void MsgSetHOSTNAME(msg_t *pMsg, uchar* pszHOSTNAME, int lenHOSTNAME);
+void MsgSetHOSTNAME(msg_t *pMsg, const uchar* pszHOSTNAME, const int lenHOSTNAME);
rsRetVal MsgSetAfterPRIOffs(msg_t *pMsg, short offs);
void MsgSetMSGoffs(msg_t *pMsg, short offs);
void MsgSetRawMsgWOSize(msg_t *pMsg, char* pszRawMsg);
-void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg, size_t lenMsg);
-rsRetVal MsgReplaceMSG(msg_t *pThis, uchar* pszMSG, int lenMSG);
+void MsgSetRawMsg(msg_t *pMsg, const char* pszRawMsg, size_t lenMsg);
+rsRetVal MsgReplaceMSG(msg_t *pThis, const uchar* pszMSG, int lenMSG);
uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, msgPropDescr_t *pProp,
rs_size_t *pPropLen, unsigned short *pbMustBeFreed, struct syslogTime *ttNow);
uchar *getRcvFrom(msg_t *pM);
@@ -193,6 +193,8 @@ void getRawMsg(msg_t *pM, uchar **pBuf, int *piLen);
rsRetVal msgAddJSON(msg_t *pM, uchar *name, struct json_object *json);
rsRetVal MsgGetSeverity(msg_t *pThis, int *piSeverity);
rsRetVal MsgDeserialize(msg_t *pMsg, strm_t *pStrm);
+rsRetVal MsgSetPropsViaJSON(msg_t *__restrict__ const pMsg, const uchar *__restrict__ const json);
+const uchar* msgGetJSONMESG(msg_t *__restrict__ const pMsg);
/* TODO: remove these five (so far used in action.c) */
uchar *getMSG(msg_t *pM);
diff --git a/runtime/net.c b/runtime/net.c
index 4d272f1..45bc621 100644
--- a/runtime/net.c
+++ b/runtime/net.c
@@ -175,7 +175,7 @@ AddPermittedPeerWildcard(permittedPeers_t *pPeer, uchar* pszStr, size_t lenStr)
assert(pPeer != NULL);
assert(pszStr != NULL);
- CHKmalloc(pNew = calloc(1, sizeof(permittedPeers_t)));
+ CHKmalloc(pNew = calloc(1, sizeof(*pNew)));
if(lenStr == 0) { /* empty domain components are permitted */
pNew->wildcardType = PEER_WILDCARD_EMPTY_COMPONENT;
@@ -713,8 +713,10 @@ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedS
memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP, iSignificantBits))
- != RS_RET_OK)
+ != 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)) {
@@ -722,7 +724,7 @@ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedS
iSignificantBits = 32;
allowIP.flags = 0;
- if((allowIP.addr.NetAddr = MALLOC(sizeof(struct sockaddr_in)))
+ if((allowIP.addr.NetAddr = (struct sockaddr *) MALLOC(sizeof(struct sockaddr_in)))
== NULL) {
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
@@ -737,8 +739,10 @@ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedS
if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP,
iSignificantBits))
- != RS_RET_OK)
+ != RS_RET_OK) {
+ free(allowIP.addr.NetAddr);
FINALIZE;
+ }
} else {
/* finally add IPv6 */
@@ -751,8 +755,10 @@ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedS
if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP,
iSignificantBits))
- != RS_RET_OK)
+ != RS_RET_OK) {
+ free(allowIP.addr.NetAddr);
FINALIZE;
+ }
}
break;
}
@@ -887,6 +893,7 @@ rsRetVal addAllowedSenderLine(char* pName, uchar** ppRestOfConfLine)
errmsg.LogError(0, iRet, "Error %d adding allowed sender entry "
"- terminating, nothing more will be added.", iRet);
rsParsDestruct(pPars);
+ free(uIP);
return(iRet);
}
}
@@ -1083,22 +1090,18 @@ void debugListenInfo(int fd, char *type)
{
char *szFamily;
int port;
- struct sockaddr sa;
- struct sockaddr_in *ipv4;
- struct sockaddr_in6 *ipv6;
+ struct sockaddr_storage sa;
socklen_t saLen = sizeof(sa);
- if(getsockname(fd, &sa, &saLen) == 0) {
- switch(sa.sa_family) {
+ if(getsockname(fd, (struct sockaddr *) &sa, &saLen) == 0) {
+ switch(sa.ss_family) {
case PF_INET:
szFamily = "IPv4";
- ipv4 = (struct sockaddr_in*)(void*) &sa;
- port = ntohs(ipv4->sin_port);
+ port = ntohs(((struct sockaddr_in *) &sa)->sin_port);
break;
case PF_INET6:
szFamily = "IPv6";
- ipv6 = (struct sockaddr_in6*)(void*) &sa;
- port = ntohs(ipv6->sin6_port);
+ port = ntohs(((struct sockaddr_in6 *) &sa)->sin6_port);
break;
default:
szFamily = "other";
@@ -1152,8 +1155,11 @@ getLocalHostname(uchar **ppName)
buf_len = 128; /* Initial guess */
CHKmalloc(buf = MALLOC(buf_len));
} else {
+ uchar *p;
+
buf_len += buf_len;
- CHKmalloc(buf = realloc (buf, buf_len));
+ CHKmalloc(p = realloc (buf, buf_len));
+ buf = p;
}
} while((gethostname((char*)buf, buf_len) == 0 && !memchr (buf, '\0', buf_len)) || errno == ENAMETOOLONG);
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
index 4ec6f62..056699d 100644
--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -121,14 +121,13 @@ readFile(uchar *pszFile, gnutls_datum_t *pBuf)
if((fd = open((char*)pszFile, O_RDONLY)) == -1) {
errmsg.LogError(0, RS_RET_FILE_NOT_FOUND, "can not read file '%s'", pszFile);
ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
-
}
if(fstat(fd, &stat_st) == -1) {
errmsg.LogError(0, 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) {
errmsg.LogError(0, RS_RET_FILE_TOO_LARGE, "file '%s' too large, max 1MB", pszFile);
@@ -142,9 +141,9 @@ readFile(uchar *pszFile, gnutls_datum_t *pBuf)
ABORT_FINALIZE(RS_RET_IO_ERROR);
}
- close(fd);
-
finalize_it:
+ if(fd != -1)
+ close(fd);
if(iRet != RS_RET_OK) {
if(pBuf->data != NULL) {
free(pBuf->data);
diff --git a/runtime/parser.c b/runtime/parser.c
index 01ed73e..5607484 100644
--- a/runtime/parser.c
+++ b/runtime/parser.c
@@ -134,7 +134,7 @@ AddParserToList(parserList_t **ppListRoot, parser_t *pParser)
/* add at tail */
pTail->pNext = pThis;
}
-
+DBGPRINTF("DDDDD: added parser '%s' to list %p\n", pParser->pName, ppListRoot);
finalize_it:
RETiRet;
}
@@ -191,6 +191,68 @@ finalize_it:
}
+/* 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 message sanitazion before we pass the data
+ * down to the parser.
+ */
+static rsRetVal
+SetDoSanitazion(parser_t *pThis, int bDoIt)
+{
+ ISOBJ_TYPE_assert(pThis, parser);
+ pThis->bDoSanitazion = bDoIt;
+ 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)
@@ -211,9 +273,46 @@ 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;
+ 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){
+ CHKiRet(SetDoSanitazion(pParser, 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:
+ RETiRet;
+}
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)
@@ -586,7 +685,10 @@ ParseMsg(msg_t *pMsg)
}
bIsSanitized = RSTRUE;
}
- localRet = pParser->pModule->mod.pm.parse(pMsg);
+ 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;
@@ -614,68 +716,6 @@ ParseMsg(msg_t *pMsg)
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 message sanitazion before we pass the data
- * down to the parser.
- */
-static rsRetVal
-SetDoSanitazion(parser_t *pThis, int bDoIt)
-{
- ISOBJ_TYPE_assert(pThis, parser);
- pThis->bDoSanitazion = bDoIt;
- 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;
-}
-
-
/* queryInterface function-- rgerhards, 2009-11-03
*/
BEGINobjQueryInterface(parser)
diff --git a/runtime/parser.h b/runtime/parser.h
index 17a7a8f..bd8a2a5 100644
--- a/runtime/parser.h
+++ b/runtime/parser.h
@@ -36,6 +36,7 @@ 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? */
};
@@ -65,6 +66,7 @@ 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/prop.c b/runtime/prop.c
index fa067bd..0686b40 100644
--- a/runtime/prop.c
+++ b/runtime/prop.c
@@ -139,15 +139,24 @@ static rsRetVal AddRef(prop_t *pThis)
/* 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 alos (very, very) slightly faster.
+ * 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;
- propConstruct(ppThis);
- SetString(*ppThis, psz, len);
- propConstructFinalize(*ppThis);
+
+ 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;
}
diff --git a/runtime/queue.c b/runtime/queue.c
index e1d46d5..8d10064 100644
--- a/runtime/queue.c
+++ b/runtime/queue.c
@@ -73,6 +73,11 @@ DEFobjCurrIf(errmsg)
DEFobjCurrIf(datetime)
DEFobjCurrIf(statsobj)
+
+#ifdef ENABLE_IMDIAG
+unsigned int iOverallQueueSize = 0;
+#endif
+
/* forward-definitions */
static inline rsRetVal doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, msg_t *pMsg);
static rsRetVal qqueueChkPersist(qqueue_t *pThis, int nUpdates);
@@ -1030,6 +1035,14 @@ qqueueAdd(qqueue_t *pThis, msg_t *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
DBGOPRINT((obj_t*) pThis, "qqueueAdd: entry added, size now log %d, phys %d entries\n",
getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis));
}
@@ -1491,6 +1504,14 @@ DoDeleteBatchFromQStore(qqueue_t *pThis, int nElem)
/* 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));
@@ -2222,7 +2243,7 @@ qqueueStart(qqueue_t *pThis) /* this is the ConstructionFinalizer */
* influenced by properties which might have been set after queueConstruct ()
*/
if(pThis->pqParent == NULL) {
- pThis->mut = (pthread_mutex_t *) MALLOC (sizeof (pthread_mutex_t));
+ 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 */
@@ -2321,6 +2342,11 @@ qqueueStart(qqueue_t *pThis) /* this is the ConstructionFinalizer */
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);
+ }
RETiRet;
}
@@ -3059,6 +3085,9 @@ static rsRetVal qqueueSetProperty(qqueue_t *pThis, var_t *pProp)
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")) {
diff --git a/runtime/queue.h b/runtime/queue.h
index 468e19b..902c3d9 100644
--- a/runtime/queue.h
+++ b/runtime/queue.h
@@ -173,14 +173,14 @@ struct queue_s {
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);
+ 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);
+ STATSCOUNTER_DEF(ctrEnqueued, mutCtrEnqueued)
+ STATSCOUNTER_DEF(ctrFull, mutCtrFull)
+ STATSCOUNTER_DEF(ctrFDscrd, mutCtrFDscrd)
+ STATSCOUNTER_DEF(ctrNFDscrd, mutCtrNFDscrd)
int ctrMaxqsize; /* NOT guarded by a mutex */
};
@@ -229,4 +229,8 @@ 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
index 22e9375..23605b1 100644
--- a/runtime/ratelimit.c
+++ b/runtime/ratelimit.c
@@ -203,6 +203,8 @@ ratelimitMsg(ratelimit_t *ratelimit, msg_t *pMsg, msg_t **ppRepMsg)
DEFiRet;
rsRetVal localRet;
+ *ppRepMsg = NULL;
+
if((pMsg->msgFlags & NEEDS_PARSING) != 0) {
if((localRet = parser.ParseMsg(pMsg)) != RS_RET_OK) {
DBGPRINTF("Message discarded, parsing error %d\n", localRet);
@@ -210,7 +212,6 @@ ratelimitMsg(ratelimit_t *ratelimit, msg_t *pMsg, msg_t **ppRepMsg)
}
}
- *ppRepMsg = NULL;
/* Only the messages having severity level at or below the
* treshold (the value is >=) are subject to ratelimiting. */
if(ratelimit->interval && (pMsg->iSeverity >= ratelimit->severity)) {
diff --git a/runtime/rsconf.c b/runtime/rsconf.c
index 9ccf05b..729911d 100644
--- a/runtime/rsconf.c
+++ b/runtime/rsconf.c
@@ -108,6 +108,16 @@ static struct cnfparamblk inppblk =
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);
@@ -254,6 +264,55 @@ CODESTARTobjDebugPrint(rsconf)
ENDobjDebugPrint(rsconf)
+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(&myparser, parserName) != RS_RET_PARSER_NOT_FOUND) {
+ errmsg.LogError(0, RS_RET_PARSER_NAME_EXISTS,
+ "parser module name '%s' already exists", cnfModName);
+ 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) {
+ errmsg.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) {
+ errmsg.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 */
rsRetVal
inputProcessCnf(struct cnfobj *o)
@@ -338,6 +397,9 @@ void cnfDoObj(struct cnfobj *o)
case CNFOBJ_GLOBAL:
glblProcessCnf(o);
break;
+ case CNFOBJ_TIMEZONE:
+ glblProcessTimezone(o);
+ break;
case CNFOBJ_MAINQ:
glblProcessMainQCnf(o);
bDestructObj = 0;
@@ -351,6 +413,9 @@ void cnfDoObj(struct cnfobj *o)
case CNFOBJ_LOOKUP_TABLE:
lookupProcessCnf(o);
break;
+ case CNFOBJ_PARSER:
+ parserProcessCnf(o);
+ break;
case CNFOBJ_TPL:
if(tplProcessCnf(o) != RS_RET_OK)
parser_errmsg("error processing template object");
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 0b6a26d..6711bd1 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -389,6 +389,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
/* 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 */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index 4bf8c05..8de7225 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -858,9 +858,16 @@ rulesetProcessCnf(struct cnfobj *o)
} else if(localRet != RS_RET_NOT_FOUND) {
ABORT_FINALIZE(localRet);
}
+
CHKiRet(rulesetConstruct(&pRuleset));
- CHKiRet(rulesetSetName(pRuleset, rsName));
- CHKiRet(rulesetConstructFinalize(loadConf, 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 */
@@ -870,7 +877,7 @@ rulesetProcessCnf(struct cnfobj *o)
for(i = 0 ; i < ar->nmemb ; ++i) {
parserName = (uchar*)es_str2cstr(ar->arr[i], NULL);
doRulesetAddParser(pRuleset, parserName);
- free(parserName);
+ /* note parserName is freed in doRulesetAddParser()! */
}
}
diff --git a/runtime/statsobj.h b/runtime/statsobj.h
index d56485d..347f639 100644
--- a/runtime/statsobj.h
+++ b/runtime/statsobj.h
@@ -139,7 +139,7 @@ PROTOTYPEObj(statsobj);
*/
#define STATSCOUNTER_DEF(ctr, mut) \
intctr_t ctr; \
- DEF_ATOMIC_HELPER_MUT64(mut);
+ DEF_ATOMIC_HELPER_MUT64(mut)
#define STATSCOUNTER_INIT(ctr, mut) \
INIT_ATOMIC_HELPER_MUT64(mut); \
diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c
index 18af7af..430e3b8 100644
--- a/runtime/stringbuf.c
+++ b/runtime/stringbuf.c
@@ -457,11 +457,14 @@ uchar* rsCStrGetSzStr(cstr_t *pThis)
* 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 *pThis, uchar **ppSz, int bRetNULL)
+rsRetVal cstrConvSzStrAndDestruct(cstr_t **ppThis, uchar **ppSz, int bRetNULL)
{
DEFiRet;
uchar* pRetBuf;
+ cstr_t *pThis;
+ assert(ppThis != NULL);
+ pThis = *ppThis;
rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
assert(ppSz != NULL);
assert(bRetNULL == 0 || bRetNULL == 1);
@@ -475,7 +478,7 @@ rsRetVal cstrConvSzStrAndDestruct(cstr_t *pThis, uchar **ppSz, int bRetNULL)
}
} else
pRetBuf = pThis->pBuf;
-
+
*ppSz = pRetBuf;
finalize_it:
@@ -484,6 +487,8 @@ finalize_it:
* also free the sz String buffer, which we pass on to the user.
*/
RSFREEOBJ(pThis);
+ *ppThis = NULL;
+
RETiRet;
}
diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h
index 9de7ce3..51a1c3a 100644
--- a/runtime/stringbuf.h
+++ b/runtime/stringbuf.h
@@ -210,7 +210,7 @@ rsRetVal rsCStrConvertToBool(cstr_t *pStr, number_t *pBool);
/* new calling interface */
rsRetVal cstrFinalize(cstr_t *pThis);
-rsRetVal cstrConvSzStrAndDestruct(cstr_t *pThis, uchar **ppSz, int bRetNULL);
+rsRetVal cstrConvSzStrAndDestruct(cstr_t **pThis, uchar **ppSz, int bRetNULL);
rsRetVal cstrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend);
/* now come inline-like functions */
diff --git a/runtime/syslogd-types.h b/runtime/syslogd-types.h
index 6947a11..4b5d135 100644
--- a/runtime/syslogd-types.h
+++ b/runtime/syslogd-types.h
@@ -106,6 +106,17 @@ struct syslogTime {
};
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/typedefs.h b/runtime/typedefs.h
index d604538..f2f5af6 100644
--- a/runtime/typedefs.h
+++ b/runtime/typedefs.h
@@ -193,6 +193,7 @@ typedef uintTiny propid_t;
#define PROP_PROCID 21
#define PROP_MSGID 22
#define PROP_PARSESUCCESS 23
+#define PROP_JSONMESG 24
#define PROP_SYS_NOW 150
#define PROP_SYS_YEAR 151
#define PROP_SYS_MONTH 152
diff --git a/runtime/wti.h b/runtime/wti.h
index b8bdac9..487abb7 100644
--- a/runtime/wti.h
+++ b/runtime/wti.h
@@ -177,21 +177,15 @@ wtiNewIParam(wti_t *const pWti, action_t *const pAction, actWrkrIParams_t **pipa
if(wrkrInfo->p.tx.currIParam == wrkrInfo->p.tx.maxIParams) {
/* we need to extend */
- dbgprintf("DDDD: extending iparams, curr max %d\n", wrkrInfo->p.tx.maxIParams);
newMax = (wrkrInfo->p.tx.maxIParams == 0) ? CONF_IPARAMS_BUFSIZE
: 2 * wrkrInfo->p.tx.maxIParams;
-dbgprintf("DDDD: realloc size %u\n", sizeof(actWrkrIParams_t) * pAction->iNumTpls * newMax);
CHKmalloc(iparams = realloc(wrkrInfo->p.tx.iparams,
sizeof(actWrkrIParams_t) * pAction->iNumTpls * newMax));
-dbgprintf("DDDD: setting memory base %u, lenBytes %u, len %u\n", wrkrInfo->p.tx.currIParam * pAction->iNumTpls,
- sizeof(actWrkrIParams_t) * pAction->iNumTpls * (newMax - wrkrInfo->p.tx.maxIParams),
- pAction->iNumTpls * (newMax - wrkrInfo->p.tx.maxIParams));
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;
}
-dbgprintf("DDDD: adding param %d for action %d\n", wrkrInfo->p.tx.currIParam, pAction->iActionNbr);
*piparams = wrkrInfo->p.tx.iparams + wrkrInfo->p.tx.currIParam * pAction->iNumTpls;
++wrkrInfo->p.tx.currIParam;