diff options
Diffstat (limited to 'runtime')
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; |