diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile.am | 12 | ||||
-rw-r--r-- | tools/logctl.c | 458 | ||||
-rw-r--r-- | tools/omfile.c | 148 | ||||
-rw-r--r-- | tools/omfwd.c | 135 | ||||
-rw-r--r-- | tools/ompipe.c | 102 | ||||
-rw-r--r-- | tools/pidfile.c | 6 | ||||
-rw-r--r-- | tools/pmrfc3164.c | 4 | ||||
-rw-r--r-- | tools/syslogd.c | 38 |
8 files changed, 839 insertions, 64 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am index e8da168d..9dd4e3bd 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,4 +1,5 @@ sbin_PROGRAMS = +bin_PROGRAMS = man_MANS = rsyslogd.8 rsyslog.conf.5 sbin_PROGRAMS += rsyslogd @@ -39,7 +40,7 @@ rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CNF_LIBS) # note: it looks like librsyslog.la must be explicitely given on LDDADD, # otherwise dependencies are not properly calculated (resulting in a # potentially incomplete build, a problem we had several times...) -rsyslogd_LDADD = $(ZLIB_LIBS) $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS) $(LIBEE_LIBS) $(LIBLOGNORM_LIBS) $(CNF_LIBS) ../grammar/libgrammar.la ../runtime/librsyslog.la +rsyslogd_LDADD = $(ZLIB_LIBS) $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS) $(LIBEE_LIBS) $(LIBLOGNORM_LIBS) $(CNF_LIBS) $(LIBUUID_LIBS) ../grammar/libgrammar.la ../runtime/librsyslog.la rsyslogd_LDFLAGS = -export-dynamic if ENABLE_DIAGTOOLS @@ -50,5 +51,14 @@ zpipe_LDADD = -lz msggen_SOURCES = msggen.c endif +if ENABLE_USERTOOLS +if ENABLE_OMMONGODB +bin_PROGRAMS += logctl +logctl_SOURCES = logctl.c +logctl_CPPFLAGS = $(LIBMONGO_CLIENT_CFLAGS) +logctl_LDADD = $(LIBMONGO_CLIENT_LIBS) +endif +endif + EXTRA_DIST = $(man_MANS) \ recover_qi.pl diff --git a/tools/logctl.c b/tools/logctl.c new file mode 100644 index 00000000..df332bc2 --- /dev/null +++ b/tools/logctl.c @@ -0,0 +1,458 @@ +/** + * logctl - a tool to access lumberjack logs in MongoDB + * ... and potentially other sources in the future. + * + * Copyright 2012 Ulrike Gerhards and Adiscon GmbH. + * + * long short + + * level l read records with level x + * severity s read records with severity x + * ret r number of records to return + * skip k number of records to skip + * sys y read records of system x + * msg m read records with message containing x + * datef f read records starting on time received x + * dateu u read records until time received x + * + * examples: + * + * logctl -f 15/05/2012-12:00:00 -u 15/05/2012-12:37:00 + * logctl -s 50 --ret 10 + * logctl -m "closed" + * logctl -l "INFO" + * logctl -s 3 + * logctl -y "ubuntu" + * + * This file is part of rsyslog. + * + * Rsyslog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" +#include <stdio.h> +#include <mongo.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <getopt.h> +#include <unistd.h> + +#define N 80 + +static struct option long_options[] = +{ + {"level", required_argument, NULL, 'l'}, + {"severity", required_argument, NULL, 's'}, + {"ret", required_argument, NULL, 'r'}, + {"skip", required_argument, NULL, 'k'}, + {"sys", required_argument, NULL, 'y'}, + {"msg", required_argument, NULL, 'm'}, + {"datef", required_argument, NULL, 'f'}, + {"dateu", required_argument, NULL, 'u'}, + {NULL, 0, NULL, 0} +}; + +struct queryopt +{ + gint32 e_sever; + gint32 e_ret; + gint32 e_skip; + char *e_date; + char *e_level; + char *e_msg; + char *e_sys; + char *e_dateu; + int bsever; + int blevel; + int bskip; + int bret; + int bsys; + int bmsg; + int bdate; + int bdatef; + int bdateu; +}; + +struct ofields +{ + const char *msg; + const char *syslog_tag; + const char *prog; + char *date; + gint64 date_r; +}; + +struct query_doc +{ + bson *query; +}; + +struct select_doc +{ + bson *select; +}; + +struct db_connect +{ + mongo_sync_connection *conn; +}; + +struct output +{ + mongo_packet *p; +}; + +struct db_cursor +{ + mongo_sync_cursor *cursor; +}; + +struct results +{ + bson *result; +}; + + + +void formater(struct ofields *fields) +{ + time_t rtime; + rtime = (time_t) (fields->date_r / 1000); + char str[N]; + strftime(str, N, "%b %d %H:%M:%S", gmtime(&rtime)); + printf("%s %s %s %s\n", str, fields->prog, fields->syslog_tag, fields->msg); + +} + +struct ofields* get_data(struct results *res) +{ + struct ofields *fields; + const char *msg; + const char *prog; + const char *level; + const char *syslog_tag; + gint64 date_r; + bson_cursor *c; + + fields = malloc(sizeof(struct ofields)); + + c = bson_find (res->result, "msg"); + if (!bson_cursor_get_string (c, &msg)) + { + perror ("bson_cursor_get_string()"); + exit (1); + } + bson_cursor_free (c); + + c = bson_find (res->result, "sys"); + if (!bson_cursor_get_string (c, &prog)) + { + perror ("bson_cursor_get_string()"); + exit (1); + } + bson_cursor_free (c); + + c = bson_find (res->result, "syslog_tag"); + if (!bson_cursor_get_string (c, &syslog_tag)) + { + perror ("bson_cursor_get_string()"); + exit (1); + } + bson_cursor_free (c); + + c = bson_find (res->result, "time_rcvd"); + if (!bson_cursor_get_utc_datetime (c, &date_r)) + { + perror ("bson_cursor_get_utc_datetime()"); + exit (1); + } + + bson_cursor_free (c); + fields->msg = msg; + fields->prog = prog; + fields->syslog_tag = syslog_tag; + fields->date_r = date_r; + + return fields; + +} + +void getoptions(int argc, char *argv[], struct queryopt *opt) +{ + int iarg; + while ((iarg = getopt_long(argc, argv, "l:s:r:k:y:f:u:m:", long_options, NULL)) != -1) + { + // check to see if a single character or long option came through + switch (iarg) + { + // short option 's' + case 's': + opt->bsever = 1; + opt->e_sever = atoi(optarg); + break; + // short option 'r' + case 'r': + opt->bret = 1; + opt->e_ret = atoi(optarg); + break; + // short option 'f' : date from + case 'f': + opt->bdate = 1; + opt->bdatef = 1; + opt->e_date = optarg; + break; + // short option 'u': date until + case 'u': + opt->bdate = 1; + opt->bdateu = 1; + opt->e_dateu = optarg; + break; + // short option 'k' + case 'k': + opt->bskip = 1; + opt->e_skip = atoi(optarg); + break; + // short option 'l' + case 'l': + opt->blevel = 1; + opt->e_level = optarg; + break; + // short option 'm' + case 'm': + opt->bmsg = 1; + opt->e_msg = optarg; + break; + // short option 'y' + case 'y': + opt->bsys = 1; + opt->e_sys = optarg; + break; + } // end switch iarg + } // end while + +} // end void getoptions + +struct select_doc* create_select() +// BSON object indicating the fields to return +{ + struct select_doc *s_doc; + s_doc = malloc(sizeof(struct select_doc)); + s_doc->select = bson_new (); + bson_append_string (s_doc->select, "syslog_tag", "s", -1); + bson_append_string (s_doc->select, "msg", "ERROR", -1); + bson_append_string (s_doc->select, "sys", "sys", -1); + bson_append_utc_datetime (s_doc->select, "time_rcvd", 1ll); + bson_finish (s_doc->select); + return s_doc; +} + +struct query_doc* create_query(struct queryopt *opt) +{ + struct query_doc *qu_doc; + bson *query_what, *order_what, *order_how, *msg_what, *date_what; + struct tm tm; + time_t t; + gint64 ts; + qu_doc = malloc(sizeof(struct query_doc)); + qu_doc->query = bson_new (); + + query_what = bson_new (); + if (opt->bsever == 1) + { + bson_append_int32 (query_what, "syslog_sever", opt->e_sever); + } + if (opt->blevel == 1) + { + bson_append_string (query_what, "level", opt->e_level, -1); + } + + if (opt->bmsg == 1) + { + msg_what = bson_new (); + bson_append_string (msg_what, "$regex", opt->e_msg, -1); + bson_append_string (msg_what, "$options", "i", -1); + bson_finish (msg_what); + bson_append_document (query_what, "msg", msg_what); + } + + if (opt->bdate == 1) + { + date_what = bson_new (); + if (opt->bdatef == 1) + { + tm.tm_isdst = -1; + strptime(opt->e_date, "%d/%m/%Y-%H:%M:%S", &tm); + tm.tm_hour = tm.tm_hour + 1; + t = mktime(&tm); + ts = 1000 * (gint64) t; + + bson_append_utc_datetime (date_what,"$gt", ts) ; + } + + if (opt->bdateu == 1) + { + tm.tm_isdst = -1; + strptime(opt->e_dateu, "%d/%m/%Y-%H:%M:%S", &tm); + tm.tm_hour = tm.tm_hour +1; + t = mktime(&tm); + ts = 1000 * (gint64) t; + bson_append_utc_datetime (date_what,"$lt", ts); + + } + bson_finish (date_what); + bson_append_document (query_what, "time_rcvd", date_what); + } + + if (opt->bsys == 1) + { + bson_append_string (query_what, "sys", opt->e_sys, -1); + } + + bson_finish (query_what); + + order_what = bson_new (); + bson_append_utc_datetime (order_what, "time_rcvd", 1ll); + bson_finish (order_what); + + bson_append_document (qu_doc->query, "$query", query_what); + bson_append_document (qu_doc->query, "$orderby", order_what); + bson_finish (qu_doc->query); + bson_free (order_what); + return qu_doc; +} + +struct db_connect* create_conn() +{ + struct db_connect *db_conn; + db_conn = malloc(sizeof(struct db_connect)); + db_conn->conn = mongo_sync_connect ("localhost", 27017, TRUE); + + if (!db_conn->conn) + { + perror ("mongo_sync_connect()"); + exit (1); + } + return db_conn; +} + +void close_conn(struct db_connect *db_conn) +{ + mongo_sync_disconnect (db_conn->conn); +} + +void free_cursor(struct db_cursor *db_c) +{ + mongo_sync_cursor_free (db_c->cursor); +} + +struct output* launch_query(struct queryopt *opt, struct select_doc *s_doc, + struct query_doc *qu_doc, + struct db_connect *db_conn) +{ + struct output *out; + out = malloc(sizeof(struct output)); + out->p = mongo_sync_cmd_query (db_conn->conn, "syslog.log", 0, + opt->e_skip, opt->e_ret, qu_doc->query, s_doc->select); + if (!out->p) + { + perror ("mongo_sync_cmd_query()"); + printf("no records found\n"); + exit (1); + } + return out; +} + +struct db_cursor* open_cursor(struct db_connect *db_conn, struct output *out) +{ + struct db_cursor *db_c; + db_c = malloc(sizeof(struct db_cursor)); + + db_c->cursor = mongo_sync_cursor_new (db_conn->conn, "syslog.log", out->p); + if (!db_c->cursor) + { + perror ("mongo_sync_cursor_new()"); + exit (1); + } + return db_c; +} + +struct results* read_data(struct db_cursor *db_c) +{ + struct results *res; + res = malloc(sizeof(struct results)); + res->result = mongo_sync_cursor_get_data (db_c->cursor); + if (!res->result) + { + perror ("mongo_sync_cursor_get_data()"); + exit (1); + } + return res; +} + +gboolean cursor_next (struct db_cursor *db_c) +{ + if (!mongo_sync_cursor_next (db_c->cursor)) + return FALSE; + else + return TRUE; + +} + +int main (int argc, char *argv[]) +{ + + struct queryopt opt; + struct ofields *fields; + struct bson_doc *doc; + struct select_doc *s_doc; + struct query_doc *qu_doc; + struct db_connect *db_conn; + struct output *out; + struct db_cursor *db_c; + struct results *res; + + opt.e_skip = 0; // standard + opt.e_ret = 0; // standard + opt.bsever = 0; + opt.blevel = 0; + opt.bdate = 0; + opt.bdateu = 0; + opt.bdatef = 0; + opt.bmsg = 0; + opt.bskip = 0; + opt.bsys = 0; + + getoptions(argc, argv, &opt); + qu_doc = create_query(&opt); // crate query + s_doc = create_select(); + db_conn = create_conn(); // create connection + out = launch_query(&opt, s_doc, qu_doc, db_conn); // launch the query + db_c = open_cursor(db_conn, out); // open cursor + + while (cursor_next(db_c)) + { + res = read_data(db_c); + fields = get_data(res); + formater(fields); // formate output + free(fields); + } + + free_cursor(db_c); + close_conn(db_conn); + + return (0); +} diff --git a/tools/omfile.c b/tools/omfile.c index 90b452bf..715b218c 100644 --- a/tools/omfile.c +++ b/tools/omfile.c @@ -121,7 +121,7 @@ struct s_dynaFileCacheEntry { typedef struct s_dynaFileCacheEntry dynaFileCacheEntry; -#define IOBUF_DFLT_SIZE 1024 /* default size for io buffers */ +#define IOBUF_DFLT_SIZE 4096 /* default size for io buffers */ #define FLUSH_INTRVL_DFLT 1 /* default buffer flush interval (in seconds) */ #define USE_ASYNCWRITER_DFLT 0 /* default buffer use async writer */ #define FLUSHONTX_DFLT 1 /* default for flush on TX end */ @@ -180,7 +180,25 @@ typedef struct configSettings_s { static configSettings_t cs; uchar *pszFileDfltTplName; /* name of the default template to use */ +struct modConfData_s { + rsconf_t *pConf; /* our overall config object */ + uchar *tplName; /* default template */ +}; + +static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ +static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */ + /* tables for interfacing with the v6 config system */ +/* module-global parameters */ +static struct cnfparamdescr modpdescr[] = { + { "template", eCmdHdlrGetWord, 0 }, +}; +static struct cnfparamblk modpblk = + { CNFPARAMBLK_VERSION, + sizeof(modpdescr)/sizeof(struct cnfparamdescr), + modpdescr + }; + /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { { "dynafilecachesize", eCmdHdlrInt, 0 }, /* legacy: dynafilecachesize */ @@ -201,7 +219,6 @@ static struct cnfparamdescr actpdescr[] = { { "file", eCmdHdlrString, 0 }, /* either "file" or ... */ { "dynafile", eCmdHdlrString, 0 }, /* "dynafile" MUST be present */ { "template", eCmdHdlrGetWord, 0 }, - //{ "", eCmdHdlrGetWord, 0 }, /* legacy: */ }; static struct cnfparamblk actpblk = { CNFPARAMBLK_VERSION, @@ -210,6 +227,21 @@ static struct cnfparamblk actpblk = }; +/* this function gets the default template. It coordinates action between + * old-style and new-style configuration parts. + */ +static inline uchar* +getDfltTpl(void) +{ + if(loadModConf != NULL && loadModConf->tplName != NULL) + return loadModConf->tplName; + else if(pszFileDfltTplName == NULL) + return (uchar*)"RSYSLOG_FileFormat"; + else + return pszFileDfltTplName; +} + + BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars pszFileDfltTplName = NULL; /* make sure this can be free'ed! */ @@ -246,6 +278,31 @@ CODESTARTdbgPrintInstInfo ENDdbgPrintInstInfo + +/* set the default template to be used + * This is a module-global parameter, and as such needs special handling. It needs to + * be coordinated with values set via the v2 config system (rsyslog v6+). What we do + * is we do not permit this directive after the v2 config system has been used to set + * the parameter. + */ +rsRetVal +setLegacyDfltTpl(void __attribute__((unused)) *pVal, uchar* newVal) +{ + DEFiRet; + + if(loadModConf != NULL && loadModConf->tplName != NULL) { + free(newVal); + errmsg.LogError(0, RS_RET_ERR, "omfile default template already set via module " + "global parameter - can no longer be changed"); + ABORT_FINALIZE(RS_RET_ERR); + } + free(pszFileDfltTplName); + pszFileDfltTplName = newVal; +finalize_it: + RETiRet; +} + + /* set the dynaFile cache size. Does some limit checking. * rgerhards, 2007-07-31 */ @@ -333,8 +390,7 @@ static rsRetVal cflineParseOutchannel(instanceData *pData, uchar* p, omodStringR */ pData->pszSizeLimitCmd = pOch->cmdOnSizeLimit; - iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, - (pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName); + iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, getDfltTpl()); finalize_it: RETiRet; @@ -647,7 +703,7 @@ doWrite(instanceData *pData, uchar *pszBuf, int lenBuf) ASSERT(pData != NULL); ASSERT(pszBuf != NULL); -dbgprintf("write to stream, pData->pStrm %p, lenBuf %d\n", pData->pStrm, lenBuf); + DBGPRINTF("write to stream, pData->pStrm %p, lenBuf %d\n", pData->pStrm, lenBuf); if(pData->pStrm != NULL){ CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf)); FINALIZE; @@ -690,6 +746,72 @@ finalize_it: } +BEGINbeginCnfLoad +CODESTARTbeginCnfLoad + loadModConf = pModConf; + pModConf->pConf = pConf; + pModConf->tplName = NULL; +ENDbeginCnfLoad + +BEGINsetModCnf + struct cnfparamvals *pvals = NULL; + int i; +CODESTARTsetModCnf + pvals = nvlstGetParams(lst, &modpblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module " + "config parameters [module(...)]"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("module (global) param blk for omfile:\n"); + cnfparamsPrint(&modpblk, pvals); + } + + for(i = 0 ; i < modpblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(modpblk.descr[i].name, "template")) { + loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + if(pszFileDfltTplName != NULL) { + errmsg.LogError(0, RS_RET_DUP_PARAM, "omfile: warning: default template " + "was already set via legacy directive - may lead to inconsistent " + "results."); + } + } else { + dbgprintf("omfile: program error, non-handled " + "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); + } + } +finalize_it: + if(pvals != NULL) + cnfparamvalsDestruct(pvals, &modpblk); +ENDsetModCnf + +BEGINendCnfLoad +CODESTARTendCnfLoad + loadModConf = NULL; /* done loading */ + /* free legacy config vars */ + free(pszFileDfltTplName); + pszFileDfltTplName = NULL; +ENDendCnfLoad + +BEGINcheckCnf +CODESTARTcheckCnf +ENDcheckCnf + +BEGINactivateCnf +CODESTARTactivateCnf + runModConf = pModConf; +ENDactivateCnf + +BEGINfreeCnf +CODESTARTfreeCnf + free(pModConf->tplName); +ENDfreeCnf + + BEGINcreateInstance CODESTARTcreateInstance pData->pStrm = NULL; @@ -698,6 +820,7 @@ ENDcreateInstance BEGINfreeInstance CODESTARTfreeInstance + free(pData->tplName); free(pData->f_fname); if(pData->bDynamicName) { dynaFileFreeCache(pData); @@ -837,9 +960,7 @@ CODESTARTnewActInst ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } - CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup((pData->tplName == NULL) ? - (uchar*)"RSYSLOG_FileFormat" : pData->tplName), - OMSR_NO_RQD_TPL_OPTS)); + CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup(getDfltTpl()), OMSR_NO_RQD_TPL_OPTS)); if(pData->bDynamicName) { /* "filename" is actually a template name, we need this as string 1. So let's add it @@ -902,8 +1023,7 @@ CODESTARTparseSelectorAct */ CODE_STD_STRING_REQUESTparseSelectorAct(2) ++p; /* eat '?' */ - CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, - (pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName)); + CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); pData->f_fname = ustrdup(fname); pData->bDynamicName = 1; pData->iCurrElt = -1; /* no current element */ @@ -919,8 +1039,7 @@ CODESTARTparseSelectorAct case '/': case '.': CODE_STD_STRING_REQUESTparseSelectorAct(1) - CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, - (pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName)); + CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); pData->f_fname = ustrdup(fname); pData->bDynamicName = 0; break; @@ -991,7 +1110,6 @@ BEGINmodExit CODESTARTmodExit objRelease(errmsg, CORE_COMPONENT); objRelease(strm, CORE_COMPONENT); - free(pszFileDfltTplName); DESTROY_ATOMIC_HELPER_MUT(mutClock); ENDmodExit @@ -999,6 +1117,8 @@ ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_OMOD_QUERIES +CODEqueryEtryPt_STD_CONF2_QUERIES +CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */ CODEqueryEtryPt_doHUP @@ -1033,7 +1153,7 @@ INITLegCnfVars CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &cs.bFailOnChown, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileforcechown", 0, eCmdHdlrGoneAway, NULL, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &cs.bEnableSync, STD_LOADABLE_MODULE_ID)); - CHKiRet(regCfSysLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszFileDfltTplName, NULL)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, setLegacyDfltTpl, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit /* vi:set ai: diff --git a/tools/omfwd.c b/tools/omfwd.c index b4a28c34..2fd24bdf 100644 --- a/tools/omfwd.c +++ b/tools/omfwd.c @@ -115,6 +115,16 @@ typedef struct configSettings_s { static configSettings_t cs; /* tables for interfacing with the v6 config system */ +/* module-global parameters */ +static struct cnfparamdescr modpdescr[] = { + { "template", eCmdHdlrGetWord, 0 }, +}; +static struct cnfparamblk modpblk = + { CNFPARAMBLK_VERSION, + sizeof(modpdescr)/sizeof(struct cnfparamdescr), + modpdescr + }; + /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { { "target", eCmdHdlrGetWord, 0 }, @@ -135,6 +145,14 @@ static struct cnfparamblk actpblk = actpdescr }; +struct modConfData_s { + rsconf_t *pConf; /* our overall config object */ + uchar *tplName; /* default template */ +}; + +static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ +static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */ + BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars @@ -151,6 +169,44 @@ ENDinitConfVars static rsRetVal doTryResume(instanceData *pData); +/* this function gets the default template. It coordinates action between + * old-style and new-style configuration parts. + */ +static inline uchar* +getDfltTpl(void) +{ + if(loadModConf != NULL && loadModConf->tplName != NULL) + return loadModConf->tplName; + else if(cs.pszTplName == NULL) + return (uchar*)"RSYSLOG_TraditionalForwardFormat"; + else + return cs.pszTplName; +} + + +/* set the default template to be used + * This is a module-global parameter, and as such needs special handling. It needs to + * be coordinated with values set via the v2 config system (rsyslog v6+). What we do + * is we do not permit this directive after the v2 config system has been used to set + * the parameter. + */ +static rsRetVal +setLegacyDfltTpl(void __attribute__((unused)) *pVal, uchar* newVal) +{ + DEFiRet; + + if(loadModConf != NULL && loadModConf->tplName != NULL) { + free(newVal); + errmsg.LogError(0, RS_RET_ERR, "omfwd default template already set via module " + "global parameter - can no longer be changed"); + ABORT_FINALIZE(RS_RET_ERR); + } + free(cs.pszTplName); + cs.pszTplName = newVal; +finalize_it: + RETiRet; +} + /* Close the UDP sockets. * rgerhards, 2009-05-29 */ @@ -189,6 +245,72 @@ DestructTCPInstanceData(instanceData *pData) netstrms.Destruct(&pData->pNS); } + +BEGINbeginCnfLoad +CODESTARTbeginCnfLoad + loadModConf = pModConf; + pModConf->pConf = pConf; + pModConf->tplName = NULL; +ENDbeginCnfLoad + +BEGINsetModCnf + struct cnfparamvals *pvals = NULL; + int i; +CODESTARTsetModCnf + pvals = nvlstGetParams(lst, &modpblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module " + "config parameters [module(...)]"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("module (global) param blk for omfwd:\n"); + cnfparamsPrint(&modpblk, pvals); + } + + for(i = 0 ; i < modpblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(modpblk.descr[i].name, "template")) { + loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + if(cs.pszTplName != NULL) { + errmsg.LogError(0, RS_RET_DUP_PARAM, "omfwd: warning: default template " + "was already set via legacy directive - may lead to inconsistent " + "results."); + } + } else { + dbgprintf("omfwd: program error, non-handled " + "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); + } + } +finalize_it: + if(pvals != NULL) + cnfparamvalsDestruct(pvals, &modpblk); +ENDsetModCnf + +BEGINendCnfLoad +CODESTARTendCnfLoad + loadModConf = NULL; /* done loading */ + /* free legacy config vars */ + free(cs.pszTplName); + cs.pszTplName = NULL; +ENDendCnfLoad + +BEGINcheckCnf +CODESTARTcheckCnf +ENDcheckCnf + +BEGINactivateCnf +CODESTARTactivateCnf + runModConf = pModConf; +ENDactivateCnf + +BEGINfreeCnf +CODESTARTfreeCnf + free(pModConf->tplName); +ENDfreeCnf + BEGINcreateInstance CODESTARTcreateInstance pData->offsSndBuf = 0; @@ -759,9 +881,7 @@ CODESTARTnewActInst } CODE_STD_STRING_REQUESTnewActInst(1) - CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup((pData->tplName == NULL) ? - (uchar*)"RSYSLOG_TraditionalForwardFormat" : (uchar*)pData->tplName), - OMSR_NO_RQD_TPL_OPTS)); + CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup(getDfltTpl()), OMSR_NO_RQD_TPL_OPTS)); CHKiRet(initTCP(pData)); CODE_STD_FINALIZERnewActInst @@ -917,8 +1037,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) cs.iTCPRebindInterval : cs.iUDPRebindInterval; /* process template */ - CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, - (cs.pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : cs.pszTplName)); + CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); if(pData->protocol == FORW_TCP) { pData->bResendLastOnRecon = cs.bResendLastOnRecon; @@ -944,8 +1063,6 @@ ENDparseSelectorAct static void freeConfigVars(void) { - free(cs.pszTplName); - cs.pszTplName = NULL; free(cs.pszStrmDrvr); cs.pszStrmDrvr = NULL; free(cs.pszStrmDrvrAuthMode); @@ -971,6 +1088,8 @@ ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_OMOD_QUERIES +CODEqueryEtryPt_STD_CONF2_QUERIES +CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */ ENDqueryEtryPt @@ -1002,7 +1121,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(net,LM_NET_FILENAME)); - CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL, &cs.pszTplName, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, setLegacyDfltTpl, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcprebindinterval", 0, eCmdHdlrInt, NULL, &cs.iTCPRebindInterval, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendudprebindinterval", 0, eCmdHdlrInt, NULL, &cs.iUDPRebindInterval, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriver", 0, eCmdHdlrGetWord, NULL, &cs.pszStrmDrvr, NULL)); diff --git a/tools/ompipe.c b/tools/ompipe.c index 30cb9bfc..d293114f 100644 --- a/tools/ompipe.c +++ b/tools/ompipe.c @@ -65,10 +65,6 @@ DEF_OMOD_STATIC_DATA DEFobjCurrIf(errmsg) -/* globals for default values */ -/* end globals for default values */ - - typedef struct _instanceData { uchar *pipe; /* pipe or template name (display only) */ uchar *tplName; /* format template to use */ @@ -82,6 +78,16 @@ typedef struct configSettings_s { static configSettings_t __attribute__((unused)) cs; /* tables for interfacing with the v6 config system */ +/* module-global parameters */ +static struct cnfparamdescr modpdescr[] = { + { "template", eCmdHdlrGetWord, 0 }, +}; +static struct cnfparamblk modpblk = + { CNFPARAMBLK_VERSION, + sizeof(modpdescr)/sizeof(struct cnfparamdescr), + modpdescr + }; + /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { { "pipe", eCmdHdlrString, CNFPARAM_REQUIRED }, @@ -93,6 +99,25 @@ static struct cnfparamblk actpblk = actpdescr }; +struct modConfData_s { + rsconf_t *pConf; /* our overall config object */ + uchar *tplName; /* default template */ +}; + +static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ +static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */ + +/* this function gets the default template */ +static inline uchar* +getDfltTpl(void) +{ + if(loadModConf != NULL && loadModConf->tplName != NULL) + return loadModConf->tplName; + else + return (uchar*)"RSYSLOG_FileFormat"; +} + + BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars ENDinitConfVars @@ -181,6 +206,71 @@ finalize_it: } +BEGINbeginCnfLoad +CODESTARTbeginCnfLoad + loadModConf = pModConf; + pModConf->pConf = pConf; + pModConf->tplName = NULL; +ENDbeginCnfLoad + +BEGINsetModCnf + struct cnfparamvals *pvals = NULL; + int i; +CODESTARTsetModCnf + pvals = nvlstGetParams(lst, &modpblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module " + "config parameters [module(...)]"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("module (global) param blk for ompipe:\n"); + cnfparamsPrint(&modpblk, pvals); + } + + for(i = 0 ; i < modpblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(modpblk.descr[i].name, "template")) { + loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + if(pszFileDfltTplName != NULL) { + errmsg.LogError(0, RS_RET_DUP_PARAM, "ompipe: warning: default template " + "was already set via legacy directive - may lead to inconsistent " + "results."); + } + } else { + dbgprintf("ompipe: program error, non-handled " + "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); + } + } +finalize_it: + if(pvals != NULL) + cnfparamvalsDestruct(pvals, &modpblk); +ENDsetModCnf + +BEGINendCnfLoad +CODESTARTendCnfLoad + loadModConf = NULL; /* done loading */ + /* free legacy config vars */ + free(pszFileDfltTplName); + pszFileDfltTplName = NULL; +ENDendCnfLoad + +BEGINcheckCnf +CODESTARTcheckCnf +ENDcheckCnf + +BEGINactivateCnf +CODESTARTactivateCnf + runModConf = pModConf; +ENDactivateCnf + +BEGINfreeCnf +CODESTARTfreeCnf + free(pModConf->tplName); +ENDfreeCnf + BEGINcreateInstance CODESTARTcreateInstance pData->pipe = NULL; @@ -273,7 +363,7 @@ CODESTARTparseSelectorAct CHKmalloc(pData->pipe = malloc(512)); ++p; CHKiRet(cflineParseFileName(p, (uchar*) pData->pipe, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, - (pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName)); + getDfltTpl())); CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct @@ -297,7 +387,9 @@ BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_OMOD_QUERIES CODEqueryEtryPt_doHUP +CODEqueryEtryPt_STD_CONF2_QUERIES CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES +CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES ENDqueryEtryPt diff --git a/tools/pidfile.c b/tools/pidfile.c index e7744513..e9601232 100644 --- a/tools/pidfile.c +++ b/tools/pidfile.c @@ -125,7 +125,7 @@ int write_pid (char *pidfile) char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); printf("Can't write pid , %s.\n", errStr); - close(fd); + fclose(f); return 0; } fflush(f); @@ -135,11 +135,11 @@ int write_pid (char *pidfile) char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); printf("Can't unlock pidfile %s, %s.\n", pidfile, errStr); - close(fd); + fclose(f); return 0; } #endif - close(fd); + fclose(f); return pid; } diff --git a/tools/pmrfc3164.c b/tools/pmrfc3164.c index 2657780d..bcded428 100644 --- a/tools/pmrfc3164.c +++ b/tools/pmrfc3164.c @@ -79,7 +79,7 @@ BEGINparse uchar bufParseTAG[CONF_TAG_MAXSIZE]; uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE]; CODESTARTparse - dbgprintf("Message will now be parsed by the legacy syslog parser (one size fits all... ;)).\n"); + DBGPRINTF("Message will now be parsed by the legacy syslog parser (one size fits all... ;)).\n"); assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* note: offAfterPRI is already the number of PRI chars (do not add one!) */ @@ -229,7 +229,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); - dbgprintf("rfc3164 parser init called\n"); + DBGPRINTF("rfc3164 parser init called\n"); bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(); /* cache value, is set only during rsyslogd option processing */ diff --git a/tools/syslogd.c b/tools/syslogd.c index b158feb3..3bd0f018 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -125,6 +125,7 @@ #include "rsconf.h" #include "dnscache.h" #include "sd-daemon.h" +#include "rainerscript.h" /* definitions for objects we access */ DEFobjCurrIf(obj) @@ -447,7 +448,6 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags) MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); -dbgprintf("ZZZZ: pLocalHostIPIF used!\n"); MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP()); MsgSetMSGoffs(pMsg, 0); /* check if we have an error code associated and, if so, @@ -801,26 +801,6 @@ static void doDie(int sig) } -/* This function frees all dynamically allocated memory for program termination. - * It must be called only immediately before exit(). It is primarily an aid - * for memory debuggers, which prevents cluttered outupt. - * rgerhards, 2008-03-20 - */ -static void -freeAllDynMemForTermination(void) -{ - free(ourConf->globals.pszConfDAGFile); - struct queuefilenames_s *qfn, *qfnDel; - - for(qfn = queuefilenames ; qfn != NULL ; ) { - qfnDel = qfn; - qfn = qfn->next; - free(qfnDel->name); - free(qfnDel); - } -} - - /* Finalize and destruct all actions. */ static inline void @@ -890,14 +870,16 @@ die(int sig) destructAllActions(); DBGPRINTF("all primary multi-thread sources have been terminated - now doing aux cleanup...\n"); + + DBGPRINTF("destructing current config...\n"); + rsconf.Destruct(&runConf); + /* rger 2005-02-22 * now clean up the in-memory structures. OK, the OS * would also take care of that, but if we do it * ourselfs, this makes finding memory leaks a lot * easier. */ - tplDeleteAll(runConf); - /* de-init some modules */ modExitIminternal(); @@ -921,15 +903,8 @@ die(int sig) /* dbgClassExit MUST be the last one, because it de-inits the debug system */ dbgClassExit(); - /* free all remaining memory blocks - this is not absolutely necessary, but helps - * us keep memory debugger logs clean and this is in aid in developing. It doesn't - * cost much time, so we do it always. -- rgerhards, 2008-03-20 - */ - freeAllDynMemForTermination(); - /* NO CODE HERE - feeelAllDynMemForTermination() must be the last thing before exit()! */ - + /* NO CODE HERE - dbgClassExit() must be the last thing before exit()! */ remove_pid(PidFile); - exit(0); /* "good" exit, this is the terminator function for rsyslog [die()] */ } @@ -1495,6 +1470,7 @@ InitGlobalClasses(void) pErrObj = "net"; CHKiRet(objUse(net, LM_NET_FILENAME)); dnscacheInit(); + initRainerscript(); finalize_it: if(iRet != RS_RET_OK) { |