From 9b1c0e2973c7222c163a8678830f1d072ba9c0c6 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 1 Feb 2008 17:51:07 +0000 Subject: very quickly hacked a rought outline of the file monitor (without any guarantees) --- plugins/imfile/imfile.c | 633 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 633 insertions(+) create mode 100644 plugins/imfile/imfile.c (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c new file mode 100644 index 00000000..38dcdc2c --- /dev/null +++ b/plugins/imfile/imfile.c @@ -0,0 +1,633 @@ +/* imtemplate.c + * + * This is NOT a real input module but a (copy)-template to create one. Please + * do NOT edit this file directly. Rather, copy it, together with the rest of + * the directory, to a new location ./plugins/im, then replace + * all references to imtemplate in Makefile.am to im. Be sure to + * fix the copyright notices to gain proper credit ;) Any derived version, + * however, needs to be placed under GPLv3 (see GPLv3 for details). If you + * do not like that policy, do not use this template or any of the header + * files. The rsyslog project greatly appreciates module contributions, so + * please consider contributing your work - even if you may think it only + * server a single very special purpose. It has turned out that at least some + * folks have similiar special purposes ;) + * + * IMPORTANT + * The comments in this file are actually the interface specification. I decided + * not to put it into a separate file as it is much simpler to keep it up to + * date when it is part of the actual template module. + * + * NAMING + * All input modules shall be named im. While this is not a hard + * requirement, it helps keeping track of things. + * + * Global variables and functions should have a prefix - use as somewhat + * longer one to prevent conflicts with rsyslog itself and other modules + * (OK, hopefully I'll have some more precise advise in the future...). + * + * INCLUDE MODULE IN THE MAIN MAKE SCRIPT + * If the module shall be provided as part of rsyslog (or simply as a build aid, + * you need to add it to the main autoconf files). To do so, you need to edit + * Makefile.am and configure.ac in the main directory. Search for imtemplate + * and copy/modify the relevant code for your plugin. + * + * DEBUGGING + * While you develop your code, you may want to add + * --enable-debug --enable-rtinst + * to your ./configure settings. These enable extra run-time checks, which cost + * a lot of performance but can help detect some of the most frequently made + * bugs. These settings will also provide you with a nice stack dump if something + * goes really wrong. + * + * MORE SAMPLES + * Remember that rsyslog ships with a number of input modules (./plugins/im*). It + * is always a good idea to have a look at them before starting your own. imudp + * may be a good, relatively trivial, sample. + * + * -------------------------------------------------------------------------------- + * + * This template was cretead on 2008-02-01 by Rainer Gerhards. + * + * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of rsyslog. + * + * Rsyslog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Rsyslog. If not, see . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" /* this is for autotools and always must be the first include */ +#include +#include +#include +#include +#include /* do NOT remove: will soon be done by the module generation macros */ +#include "rsyslog.h" /* error codes etc... */ +#include "syslogd.h" +#include "cfsysline.h" /* access to config file objects */ +#include "module-template.h" /* generic module interface code - very important, read it! */ +#include "srUtils.h" /* some utility functions */ +#include "msg.h" + +MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ + +/* defines */ + +/* Module static data */ +DEF_IMOD_STATIC_DATA /* must be present, starts static data */ + +/* Here, define whatever static data is needed. Is it suggested that static variables only are + * used (not externally visible). If you need externally visible variables, make sure you use a + * prefix in order not to conflict with other modules or rsyslogd itself (also see comment + * at file header). + */ +/* static int imtemplateWhateverVar = 0; */ + +typedef struct fileInfo_s { + uchar *pszFileName; + uchar *pszTag; + int64 offsLast; /* offset last read from */ + int iFacility; + int iSeverity; + int fd; /*its file descriptor (-1 if closed) */ +} fileInfo_t; + + +/* config variables */ +static uchar *pszFileName = NULL; +static uchar *pszFileTag = NULL; +static int iFacility; +static int iSeverity; + +static int iFilPtr = 0; +#define MAX_INPUT_FILES 100 +static fileInfo_t files[MAX_INPUT_FILES]; + +/* instanceData must be defined to keep the framework happy, but it currently + * is of no practical use. This may change in later revisions of the plugin + * interface. + */ +typedef struct _instanceData { +} instanceData; + +/* config settings */ + + +/* You may add any functions that you feel are useful for your needs. No specific restrictions + * apply, but we suggest that you use the "iRet" call order, which enables you to use debug + * support for your own functions and which also makes it easy to communicate exceptions back + * to the upstream caller (rsyslog framework, for example. + * + * The function below is a sample of how one of your functions may look like. Again, the sample + * below is *not* needed to be present in order to meet the interface requirements. + * + * Be sure to use static functions (suggested) or prefixes to prevent name conflicts -- see file + * header for more information. + */ +static rsRetVal /* rsRetVal is our generic error-reporting return type */ +imtemplateMyFunc(int iMyParam) +{ + DEFiRet; /* define iRet, the return code and other plumbing */ + /* define your local variables here */ + + /* code whatever you need to code here. The "iRet" system can be helpful: + * + * CHKiRet(function(param1, param2, ...)); + * calls a function and checks if it returns RS_RET_OK. If so, work + * proceeds. If some other code is returned, the function is aborted + * and control transferred to finalize_it (which you need to define) + * + * CHKiRet_Hdlr(function(param1, param2, ...)) + * much like CHKiRet, but allows you to specify your own code that is + * executed if the function does not return RS_RET_OK, e.g.: + * CHKiRet_Hdlr(function(a, b)) { + * ... some error handling here ... + * } + * control is not transferred to finalize_it, except if you use one + * of the relevant macros (described below) + * + * FINALIZE + * immediately transfers control to finalize_it, using the current + * value of iRet, e.g. + * if(bDone) + * FINALIZE; + * + * ABORT_FINALIZE(retcode) + * just like FINALIZE, except that iRet is set to the provided error + * code before control is transferred, e.g. + * if((ptr = malloc(20)) == NULL) + * ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); + * + * In order for all this to work, you need to define finalize_it, e.g. + * + * finalize_it: + * RETiRet; + * + * RETiRet does some housekeeping and then does a "return iRet" to transfer + * control back to the caller. There shall only be one function exit and + * it shall be via RETiRet, preferrably at the end of the function code. + * + */ + +finalize_it: + /* clean up anything that needs to be cleaned up if processing did not + * go well, for example: + */ + if(iRet != RS_RET_OK) { + /* cleanup, e.g. + * free(somePtr); + */ + } + + RETiRet; +} + + +/* enqueue the read file line as a message + */ +static rsRetVal enqLine(fileInfo_t *pInfo, uchar *pLine) +{ + + DEFiRet; + msg_t *pMsg; + int flags = 0; + int pri; + + CHKiRet(msgConstruct(&pMsg)); + MsgSetUxTradMsg(pMsg, pLine); + MsgSetRawMsg(pMsg, pLine); + MsgSetHOSTNAME(pMsg, LocalHostName); + MsgSetTAG(pMsg, pInfo->pszTag); + pMsg->iFacility = pInfo->iFacility; + pMsg->iSeverity = pInfo->iSeverity; + pMsg->bParseHOSTNAME = 0; + getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ + logmsg(pri, pMsg, flags); /* some time, CHKiRet() will work here, too [today NOT!] */ +finalize_it: + RETiRet; +} + + +/* poll a file, need to check file rollover etc. open file if not open */ +static rsRetVal pollFile(fileInfo_t *pThis) +{ + DEFiRet; + char *pszLine; + int bAllNewLinesRead; /* set to 1 if all new lines are read */ + + if(pThis->fd == -1) { + /* open file */ + /* move to offset */ + } + + bAllNewLinesRead = 0; + while(!bAllNewLinesRead) { + /* do read file, put pointer to file line in pszLine */ + pszLine = "MyLine of file data..."; // dummy + + /* do the magic ;) */ + CHKiRet(enqLine(pThis, pszLine)); + } + + /* save the offset back to structure! */ + +finalize_it: + RETiRet; +} + + +/* This function is the cancel cleanup handler. It is called when rsyslog decides the + * module must be stopped, what most probably happens during shutdown of rsyslogd. When + * this function is called, the runInput() function (below) is already terminated - somewhere + * in the middle of what it was doing. The cancel cleanup handler below should take + * care of any locked mutexes and such, things that really need to be cleaned up + * before processing continues. In general, many plugins do not need to provide + * any code at all here. + * + * IMPORTANT: the calling interface of this function can NOT be modified. It actually is + * called by pthreads. The provided argument is currently not being used. + */ +/* ------------------------------------------------------------------------------------------ * + * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ +static void +inputModuleCleanup(void *arg) +{ + BEGINfunc +/* END no-touch zone * + * ------------------------------------------------------------------------------------------ */ + + + + /* so far not needed */ + + + +/* ------------------------------------------------------------------------------------------ * + * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ + ENDfunc +} +/* END no-touch zone * + * ------------------------------------------------------------------------------------------ */ + + +/* This function is called by the framework to gather the input. The module stays + * most of its lifetime inside this function. It MUST NEVER exit this function. Doing + * so would end module processing and rsyslog would NOT reschedule the module. If + * you exit from this function, you violate the interface specification! + * + * So how is it terminated? When it is time to terminate, rsyslog actually cancels + * the threads. This may sound scary, but is not. There is a cancel cleanup handler + * defined (the function directly above). See comments there for specifics. + * + * runInput is always called on a single thread. If the module neees multiple threads, + * it is free to create them. HOWEVER, it must make sure that any threads created + * are killed and joined in the cancel cleanup handler. + */ +BEGINrunInput + int i; + /* define any local variables you need here */ +CODESTARTrunInput + /* ------------------------------------------------------------------------------------------ * + * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ + pthread_cleanup_push(inputModuleCleanup, NULL); + while(1) { /* endless loop - do NOT break; out of it! */ + /* END no-touch zone * + * ------------------------------------------------------------------------------------------ */ + + /* your code here */ + + /* All rsyslog objects (see other modules, e.g. msg.c) are available + * to your here. Some useful things are: + * + * logerror("string"); + * logs an error message as syslogd + * + * logerror("string with %s", uchar* ptr) + * just like logerror, but with a variable pointer to a string + * + * The safe way to obtain a system error message is: + * char errStr[1024]; // 1024 is just a (relatively) safe bet... + * rs_strerror_r(errno, errStr, sizeof(errStr)); + * logerror("error occured: %s", errStr); // optional, of course... + * + * To log something to the debug log, simply use + * dbgprintf("fmtstring %d, %s\n", 4711, "like in printf"); + * Be sure to include a newline '\n' at the end of the message, else + * the debug log will become quite cluttered... + * + * There are several ways how a message can be enqueued. This part of the + * interface is currently underspecified. Have a look at the function definitions + * in syslogd.c (sorry, folks...). + * + * If you received a full syslog message that must be decoded by a message + * parser, printchopped() is the way to go. It's not just a funny name + * but also a quite some legacy. Consequently, its interface is, ummm, not + * well designed. + * printchopped((char*)fromHost, (char*) pRcvBuf, lenRcvd, fd, bParseHost); + * fromHost + * is the host that we received the message from (a string) + * pRcvBuf + * is the received (to-be-decoded) message + * lenRcvd + * is the length of the received message. Please note that pRcvBuf is + * NOT a standard C-string. Most importantly it is NOT expected to be + * \0-terminated. Thus the lenght is vitally imporant (if it is wrong, + * rsyslogd will probably segfault). + * fd + * is the file descriptor that the message was received from. It is + * purely used for displaying purposes. If you don't have a file + * descriptor, simply provide the value 0. + * bParseHost + * is a boolean (0-no, 1-yes). It tells the parser whether or not + * a hostname should be parsed from the message. This is important + * for sources that are known not to provide a hostname. + * + * Another, more elaborate, way is to create the message object ourselves and + * pass it to the rule engine. That way is more appropriate if the message + * does not need to be parsed, for example when reading text (log) files. In that way, + * we can set the message properties as of our liking. This is how it works: + * + msg_t *pMsg; + CHKiRet(msgConstruct(&pMsg)); + MsgSetUxTradMsg(pMsg, msg); + MsgSetRawMsg(pMsg, msg); + MsgSetHOSTNAME(pMsg, LocalHostName); + MsgSetTAG(pMsg, "rsyslogd:"); + pMsg->iFacility = LOG_FAC(pri); + pMsg->iSeverity = LOG_PRI(pri); + pMsg->bParseHOSTNAME = 0; + getCurrTime(&(pMsg->tTIMESTAMP)); / * use the current time! * / + flags |= INTERNAL_MSG; + logmsg(pri, pMsg, flags); / * some time, CHKiRet() will work here, too [today NOT!] * / + * + * Note that UxTradMsg is a wild construct. For the time being, set it to + * the raw message text. I am hard thinking at dropping that beast at all... + * + * This example probably does not set all message properties (but the ones + * that are of practical importance). If you need all, check msg.h. Use + * method access functions whereever possible, unfortunately not all structure + * members are currently exposed in that clean way - so you sometimes need + * to access them directly (it goes without saying that we will fix that + * over time ;)). + */ + + + for(i = 0 ; i < iFilPtr ; ++i) { + pollFile(&files[i]); + } + + srSleep(1,0); + + /* ------------------------------------------------------------------------------------------ * + * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ + } + /*NOTREACHED*/ + + pthread_cleanup_pop(0); /* just for completeness, but never called... */ + RETiRet; /* use it to make sure the housekeeping is done! */ +ENDrunInput + /* END no-touch zone * + * ------------------------------------------------------------------------------------------ */ + + +/* The function is called by rsyslog before runInput() is called. It is a last chance + * to set up anything specific. Most importantly, it can be used to tell rsyslog if the + * input shall run or not. The idea is that if some config settings (or similiar things) + * are not OK, the input can tell rsyslog it will not execute. To do so, return + * RS_RET_NO_RUN or a specific error code. If RS_RET_OK is returned, rsyslog will + * proceed and call the runInput() entry point. + */ +BEGINwillRun + /* place any variables needed here */ +CODESTARTwillRun + + /* ... your code here ... */ + + /* Just to give you an idea, here are some samples (from the actual imudp module: + * + if(udpLstnSocks == NULL) + ABORT_FINALIZE(RS_RET_NO_RUN); + + if((pRcvBuf = malloc(MAXLINE * sizeof(char))) == NULL) { + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); + } + * + */ + if(iFilPtr == 0) { + logerror("No files configured to be monitored"); + ABORT_FINALIZE(RS_RET_NO_RUN); + } + +finalize_it: +ENDwillRun + + +/* This function is called by the framework after runInput() has been terminated. It + * shall free any resources and prepare the module for unload. + * + * So it is important that runInput() keeps track of what needs to be cleaned up. + * Objects to think about are files (must be closed), network connections, threads (must + * be stopped and joined) and memory (must be freed). Of course, there are a myriad + * of other things, so use your own judgement what you need to do. + * + * Another important chore of this function is to persist whatever state the module + * needs to persist. Unfortunately, there is currently no standard way of doing that. + * Future version of the module interface will probably support it, but that doesn't + * help you right at the moment. In general, it is suggested that anything that needs + * to be persisted is saved in a file, whose name and location is passed in by a + * module-specific config directive. + */ +BEGINafterRun + /* place any variables needed here */ +CODESTARTafterRun + + /* ... do cleanup here ... */ + + /* if you have a string config variable, remember to free its content: + * + if(pszStr != NULL) { + free(pszStr); + pszStr = NULL; + } + */ + + /* loop through file array and close everything that's open */ + + /* somehow persist the file arry information, at least the offset! Must be + * able to get back up an rolling even when the order of files inside the + * array changes (think of config changes!). + */ +ENDafterRun + + +/* The following entry points are defined in module-template.h. + * In general, they need to be present, but you do NOT need to provide + * any code here. + */ +BEGINfreeInstance +CODESTARTfreeInstance +ENDfreeInstance + + +BEGINdbgPrintInstInfo +CODESTARTdbgPrintInstInfo +ENDdbgPrintInstInfo + + +BEGINmodExit +CODESTARTmodExit +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_IMOD_QUERIES +ENDqueryEtryPt + + +/* The following function shall reset all configuration variables to their + * default values. The code provided in modInit() below registers it to be + * called on "$ResetConfigVariables". You may also call it from other places, + * but in general this is not necessary. Once runInput() has been called, this + * function here is never again called. + */ +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +{ + DEFiRet; + + /* if you have string variables in you config settings, you need to do this: + if(pszStr != NULL) { + free(pszStr); + pszStr = NULL; + } + * Note that it is vitally important that the pointer is set to NULL, because + * otherwise the framework handler will try to free it a second time when + * a new value is set! + */ + + if(pszFileName != NULL) { + free(pszFileName); + pszFileName = NULL; + } + + if(pszFileTag != NULL) { + free(pszFileTag); + pszFileTag = NULL; + } + + + /* set defaults... */ + iFacility = 12; /* RFC 3164!! */ + iSeverity = 4; + + /* ... your code here ... */ + + + RETiRet; +} + + +/* add a new monitor */ +static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) +{ + DEFiRet; + fileInfo_t *pThis; + + if(iFilPtr < MAX_INPUT_FILES) { + pThis = &files[iFilPtr]; + ++iFilPtr; + pThis->pszFileName = (uchar*) strdup((char*) pszFileName); + pThis->pszTag = (uchar*) strdup((char*) pszFileTag); + pThis->iSeverity = iSeverity; + pThis->iFacility = iFacility; + pThis->offsLast = 0; + /* ... whatever else you need ... */ + } else { + logerror("Too many file monitors configured - ignoring this one"); + } + RETiRet; +} + +/* modInit() is called once the module is loaded. It must perform all module-wide + * initialization tasks. There are also a number of housekeeping tasks that the + * framework requires. These are handled by the macros. Please note that the + * complexity of processing is depending on the actual module. However, only + * thing absolutely necessary should be done here. Actual app-level processing + * is to be performed in runInput(). A good sample of what to do here may be to + * set some variable defaults. The most important thing probably is registration + * of config command handlers. + */ +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = 1; /* interface spec version this module is written to (currently always 1) */ +CODEmodInit_QueryRegCFSLineHdlr + /* register config file handlers + * For details, see cfsysline.c/.h. The config file is automatically handled. In general, + * a pointer to a variable receiving the value and the config directive is to be supplied. + * A custom function pointer can only be provided, which then is called when the config + * directive appears. Limit this to cases where it is absolutely necessary. The + * STD_LOADABLE_MODULE_ID is a value that identifies the module. It is use to automatically + * unregister the module's config file handlers upon module unload. Do NOT use any other + * value for this parameter! Available Syntaxes (supported types) can be seen in cfsysline.h, + * the ecslCmdHdrlType enum has all that are currently defined. + * + * Config file directives should always be along the lines of + * + * $InputObjObjName + * + * An example would be $InputImtemplateRetriesMax. This is currently not enforced, + * but when we get to our new config file format and reader, this becomes quite + * important. + * + * Please note that config directives must be provided in lower case. The engine + * makes the mapping (what currently means case-insensitive comparison). The dollar + * sign is NOT part of the directive and thus not specified. + * + * Some samples: + * + * A hypothetical integer variable: + * CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputimtemplatemessagenumber", 0, eCmdHdlrInt, + NULL, &intVariable, STD_LOADABLE_MODULE_ID)); + * + * and a hypothetical string variable: + * CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputimtemplatemessagetext", 0, eCmdHdlrGetWord, + * NULL, &pszBindAddr, STD_LOADABLE_MODULE_ID)); + */ + + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, + NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, + NULL, &pszFileTag, STD_LOADABLE_MODULE_ID)); + /* use numerical values as of RFC 3164 for the time being... */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrInt, + NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilesfacility", 0, eCmdHdlrInt, + NULL, &iFacility, STD_LOADABLE_MODULE_ID)); + /* things missing, e.g. polling intervall... */ + /* that command ads a new file! */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, + addMonitor, NULL, STD_LOADABLE_MODULE_ID)); + /* whenever config variables exist, they should be resettable via $ResetConfigVariables. + * The following line adds our handler for that. Note that if you do not have any config + * variables at all (unlikely, I think...), you can remove this handler. + */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, + resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); + + /* ... do whatever else you need to do, but keep it brief ... */ + +ENDmodInit +/* + * vim:set ai: + */ -- cgit v1.2.3 From 89a9e10228e18bfc175515c6c389a3780be29095 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 13 Feb 2008 07:29:44 +0000 Subject: cleaned up imfile.c --- plugins/imfile/imfile.c | 302 +++--------------------------------------------- 1 file changed, 19 insertions(+), 283 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 38dcdc2c..1b07ee62 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -1,52 +1,9 @@ -/* imtemplate.c +/* imfile.c * - * This is NOT a real input module but a (copy)-template to create one. Please - * do NOT edit this file directly. Rather, copy it, together with the rest of - * the directory, to a new location ./plugins/im, then replace - * all references to imtemplate in Makefile.am to im. Be sure to - * fix the copyright notices to gain proper credit ;) Any derived version, - * however, needs to be placed under GPLv3 (see GPLv3 for details). If you - * do not like that policy, do not use this template or any of the header - * files. The rsyslog project greatly appreciates module contributions, so - * please consider contributing your work - even if you may think it only - * server a single very special purpose. It has turned out that at least some - * folks have similiar special purposes ;) + * This is the input module for reading text file data. A text file is a + * non-binary file who's lines are delemited by the \n character. * - * IMPORTANT - * The comments in this file are actually the interface specification. I decided - * not to put it into a separate file as it is much simpler to keep it up to - * date when it is part of the actual template module. - * - * NAMING - * All input modules shall be named im. While this is not a hard - * requirement, it helps keeping track of things. - * - * Global variables and functions should have a prefix - use as somewhat - * longer one to prevent conflicts with rsyslog itself and other modules - * (OK, hopefully I'll have some more precise advise in the future...). - * - * INCLUDE MODULE IN THE MAIN MAKE SCRIPT - * If the module shall be provided as part of rsyslog (or simply as a build aid, - * you need to add it to the main autoconf files). To do so, you need to edit - * Makefile.am and configure.ac in the main directory. Search for imtemplate - * and copy/modify the relevant code for your plugin. - * - * DEBUGGING - * While you develop your code, you may want to add - * --enable-debug --enable-rtinst - * to your ./configure settings. These enable extra run-time checks, which cost - * a lot of performance but can help detect some of the most frequently made - * bugs. These settings will also provide you with a nice stack dump if something - * goes really wrong. - * - * MORE SAMPLES - * Remember that rsyslog ships with a number of input modules (./plugins/im*). It - * is always a good idea to have a look at them before starting your own. imudp - * may be a good, relatively trivial, sample. - * - * -------------------------------------------------------------------------------- - * - * This template was cretead on 2008-02-01 by Rainer Gerhards. + * Work originally begun on 2008-02-01 by Rainer Gerhards * * Copyright 2008 Rainer Gerhards and Adiscon GmbH. * @@ -97,6 +54,7 @@ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ typedef struct fileInfo_s { uchar *pszFileName; uchar *pszTag; + uchar *pszStateFile; /* file in which state between runs is to be stored */ int64 offsLast; /* offset last read from */ int iFacility; int iSeverity; @@ -107,6 +65,7 @@ typedef struct fileInfo_s { /* config variables */ static uchar *pszFileName = NULL; static uchar *pszFileTag = NULL; +static uchar *pszStateFile = NULL; static int iFacility; static int iSeverity; @@ -124,91 +83,20 @@ typedef struct _instanceData { /* config settings */ -/* You may add any functions that you feel are useful for your needs. No specific restrictions - * apply, but we suggest that you use the "iRet" call order, which enables you to use debug - * support for your own functions and which also makes it easy to communicate exceptions back - * to the upstream caller (rsyslog framework, for example. - * - * The function below is a sample of how one of your functions may look like. Again, the sample - * below is *not* needed to be present in order to meet the interface requirements. - * - * Be sure to use static functions (suggested) or prefixes to prevent name conflicts -- see file - * header for more information. - */ -static rsRetVal /* rsRetVal is our generic error-reporting return type */ -imtemplateMyFunc(int iMyParam) -{ - DEFiRet; /* define iRet, the return code and other plumbing */ - /* define your local variables here */ - - /* code whatever you need to code here. The "iRet" system can be helpful: - * - * CHKiRet(function(param1, param2, ...)); - * calls a function and checks if it returns RS_RET_OK. If so, work - * proceeds. If some other code is returned, the function is aborted - * and control transferred to finalize_it (which you need to define) - * - * CHKiRet_Hdlr(function(param1, param2, ...)) - * much like CHKiRet, but allows you to specify your own code that is - * executed if the function does not return RS_RET_OK, e.g.: - * CHKiRet_Hdlr(function(a, b)) { - * ... some error handling here ... - * } - * control is not transferred to finalize_it, except if you use one - * of the relevant macros (described below) - * - * FINALIZE - * immediately transfers control to finalize_it, using the current - * value of iRet, e.g. - * if(bDone) - * FINALIZE; - * - * ABORT_FINALIZE(retcode) - * just like FINALIZE, except that iRet is set to the provided error - * code before control is transferred, e.g. - * if((ptr = malloc(20)) == NULL) - * ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - * - * In order for all this to work, you need to define finalize_it, e.g. - * - * finalize_it: - * RETiRet; - * - * RETiRet does some housekeeping and then does a "return iRet" to transfer - * control back to the caller. There shall only be one function exit and - * it shall be via RETiRet, preferrably at the end of the function code. - * - */ - -finalize_it: - /* clean up anything that needs to be cleaned up if processing did not - * go well, for example: - */ - if(iRet != RS_RET_OK) { - /* cleanup, e.g. - * free(somePtr); - */ - } - - RETiRet; -} - - /* enqueue the read file line as a message */ static rsRetVal enqLine(fileInfo_t *pInfo, uchar *pLine) { - DEFiRet; msg_t *pMsg; int flags = 0; int pri; CHKiRet(msgConstruct(&pMsg)); - MsgSetUxTradMsg(pMsg, pLine); - MsgSetRawMsg(pMsg, pLine); + MsgSetUxTradMsg(pMsg, (char*)pLine); + MsgSetRawMsg(pMsg, (char*)pLine); MsgSetHOSTNAME(pMsg, LocalHostName); - MsgSetTAG(pMsg, pInfo->pszTag); + MsgSetTAG(pMsg, (char*)pInfo->pszTag); pMsg->iFacility = pInfo->iFacility; pMsg->iSeverity = pInfo->iSeverity; pMsg->bParseHOSTNAME = 0; @@ -223,7 +111,7 @@ finalize_it: static rsRetVal pollFile(fileInfo_t *pThis) { DEFiRet; - char *pszLine; + uchar *pszLine; int bAllNewLinesRead; /* set to 1 if all new lines are read */ if(pThis->fd == -1) { @@ -234,7 +122,6 @@ static rsRetVal pollFile(fileInfo_t *pThis) bAllNewLinesRead = 0; while(!bAllNewLinesRead) { /* do read file, put pointer to file line in pszLine */ - pszLine = "MyLine of file data..."; // dummy /* do the magic ;) */ CHKiRet(enqLine(pThis, pszLine)); @@ -261,7 +148,7 @@ finalize_it: /* ------------------------------------------------------------------------------------------ * * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ static void -inputModuleCleanup(void *arg) +inputModuleCleanup(void __attribute__((unused)) *arg) { BEGINfunc /* END no-touch zone * @@ -296,7 +183,6 @@ inputModuleCleanup(void *arg) */ BEGINrunInput int i; - /* define any local variables you need here */ CODESTARTrunInput /* ------------------------------------------------------------------------------------------ * * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ @@ -305,84 +191,6 @@ CODESTARTrunInput /* END no-touch zone * * ------------------------------------------------------------------------------------------ */ - /* your code here */ - - /* All rsyslog objects (see other modules, e.g. msg.c) are available - * to your here. Some useful things are: - * - * logerror("string"); - * logs an error message as syslogd - * - * logerror("string with %s", uchar* ptr) - * just like logerror, but with a variable pointer to a string - * - * The safe way to obtain a system error message is: - * char errStr[1024]; // 1024 is just a (relatively) safe bet... - * rs_strerror_r(errno, errStr, sizeof(errStr)); - * logerror("error occured: %s", errStr); // optional, of course... - * - * To log something to the debug log, simply use - * dbgprintf("fmtstring %d, %s\n", 4711, "like in printf"); - * Be sure to include a newline '\n' at the end of the message, else - * the debug log will become quite cluttered... - * - * There are several ways how a message can be enqueued. This part of the - * interface is currently underspecified. Have a look at the function definitions - * in syslogd.c (sorry, folks...). - * - * If you received a full syslog message that must be decoded by a message - * parser, printchopped() is the way to go. It's not just a funny name - * but also a quite some legacy. Consequently, its interface is, ummm, not - * well designed. - * printchopped((char*)fromHost, (char*) pRcvBuf, lenRcvd, fd, bParseHost); - * fromHost - * is the host that we received the message from (a string) - * pRcvBuf - * is the received (to-be-decoded) message - * lenRcvd - * is the length of the received message. Please note that pRcvBuf is - * NOT a standard C-string. Most importantly it is NOT expected to be - * \0-terminated. Thus the lenght is vitally imporant (if it is wrong, - * rsyslogd will probably segfault). - * fd - * is the file descriptor that the message was received from. It is - * purely used for displaying purposes. If you don't have a file - * descriptor, simply provide the value 0. - * bParseHost - * is a boolean (0-no, 1-yes). It tells the parser whether or not - * a hostname should be parsed from the message. This is important - * for sources that are known not to provide a hostname. - * - * Another, more elaborate, way is to create the message object ourselves and - * pass it to the rule engine. That way is more appropriate if the message - * does not need to be parsed, for example when reading text (log) files. In that way, - * we can set the message properties as of our liking. This is how it works: - * - msg_t *pMsg; - CHKiRet(msgConstruct(&pMsg)); - MsgSetUxTradMsg(pMsg, msg); - MsgSetRawMsg(pMsg, msg); - MsgSetHOSTNAME(pMsg, LocalHostName); - MsgSetTAG(pMsg, "rsyslogd:"); - pMsg->iFacility = LOG_FAC(pri); - pMsg->iSeverity = LOG_PRI(pri); - pMsg->bParseHOSTNAME = 0; - getCurrTime(&(pMsg->tTIMESTAMP)); / * use the current time! * / - flags |= INTERNAL_MSG; - logmsg(pri, pMsg, flags); / * some time, CHKiRet() will work here, too [today NOT!] * / - * - * Note that UxTradMsg is a wild construct. For the time being, set it to - * the raw message text. I am hard thinking at dropping that beast at all... - * - * This example probably does not set all message properties (but the ones - * that are of practical importance). If you need all, check msg.h. Use - * method access functions whereever possible, unfortunately not all structure - * members are currently exposed in that clean way - so you sometimes need - * to access them directly (it goes without saying that we will fix that - * over time ;)). - */ - - for(i = 0 ; i < iFilPtr ; ++i) { pollFile(&files[i]); } @@ -409,21 +217,7 @@ ENDrunInput * proceed and call the runInput() entry point. */ BEGINwillRun - /* place any variables needed here */ CODESTARTwillRun - - /* ... your code here ... */ - - /* Just to give you an idea, here are some samples (from the actual imudp module: - * - if(udpLstnSocks == NULL) - ABORT_FINALIZE(RS_RET_NO_RUN); - - if((pRcvBuf = malloc(MAXLINE * sizeof(char))) == NULL) { - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - } - * - */ if(iFilPtr == 0) { logerror("No files configured to be monitored"); ABORT_FINALIZE(RS_RET_NO_RUN); @@ -451,17 +245,6 @@ ENDwillRun BEGINafterRun /* place any variables needed here */ CODESTARTafterRun - - /* ... do cleanup here ... */ - - /* if you have a string config variable, remember to free its content: - * - if(pszStr != NULL) { - free(pszStr); - pszStr = NULL; - } - */ - /* loop through file array and close everything that's open */ /* somehow persist the file arry information, at least the offset! Must be @@ -506,16 +289,6 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a { DEFiRet; - /* if you have string variables in you config settings, you need to do this: - if(pszStr != NULL) { - free(pszStr); - pszStr = NULL; - } - * Note that it is vitally important that the pointer is set to NULL, because - * otherwise the framework handler will try to free it a second time when - * a new value is set! - */ - if(pszFileName != NULL) { free(pszFileName); pszFileName = NULL; @@ -526,14 +299,16 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a pszFileTag = NULL; } + if(pszStateFile != NULL) { + free(pszFileTag); + pszFileTag = NULL; + } + /* set defaults... */ - iFacility = 12; /* RFC 3164!! */ + iFacility = 12; /* see RFC 3164 for values */ iSeverity = 4; - /* ... your code here ... */ - - RETiRet; } @@ -552,7 +327,6 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; pThis->offsLast = 0; - /* ... whatever else you need ... */ } else { logerror("Too many file monitors configured - ignoring this one"); } @@ -572,43 +346,12 @@ BEGINmodInit() CODESTARTmodInit *ipIFVersProvided = 1; /* interface spec version this module is written to (currently always 1) */ CODEmodInit_QueryRegCFSLineHdlr - /* register config file handlers - * For details, see cfsysline.c/.h. The config file is automatically handled. In general, - * a pointer to a variable receiving the value and the config directive is to be supplied. - * A custom function pointer can only be provided, which then is called when the config - * directive appears. Limit this to cases where it is absolutely necessary. The - * STD_LOADABLE_MODULE_ID is a value that identifies the module. It is use to automatically - * unregister the module's config file handlers upon module unload. Do NOT use any other - * value for this parameter! Available Syntaxes (supported types) can be seen in cfsysline.h, - * the ecslCmdHdrlType enum has all that are currently defined. - * - * Config file directives should always be along the lines of - * - * $InputObjObjName - * - * An example would be $InputImtemplateRetriesMax. This is currently not enforced, - * but when we get to our new config file format and reader, this becomes quite - * important. - * - * Please note that config directives must be provided in lower case. The engine - * makes the mapping (what currently means case-insensitive comparison). The dollar - * sign is NOT part of the directive and thus not specified. - * - * Some samples: - * - * A hypothetical integer variable: - * CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputimtemplatemessagenumber", 0, eCmdHdlrInt, - NULL, &intVariable, STD_LOADABLE_MODULE_ID)); - * - * and a hypothetical string variable: - * CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputimtemplatemessagetext", 0, eCmdHdlrGetWord, - * NULL, &pszBindAddr, STD_LOADABLE_MODULE_ID)); - */ - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, NULL, &pszFileTag, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord, + NULL, &pszStateFile, STD_LOADABLE_MODULE_ID)); /* use numerical values as of RFC 3164 for the time being... */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrInt, NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); @@ -618,15 +361,8 @@ CODEmodInit_QueryRegCFSLineHdlr /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, addMonitor, NULL, STD_LOADABLE_MODULE_ID)); - /* whenever config variables exist, they should be resettable via $ResetConfigVariables. - * The following line adds our handler for that. Note that if you do not have any config - * variables at all (unlikely, I think...), you can remove this handler. - */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); - - /* ... do whatever else you need to do, but keep it brief ... */ - ENDmodInit /* * vim:set ai: -- cgit v1.2.3 From 13dfec032daeed349dbe2be9251dbc5627264d79 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 13 Feb 2008 07:32:46 +0000 Subject: changed interface of logmsg() to make it more straightforward --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 1b07ee62..d37df02d 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -101,7 +101,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, uchar *pLine) pMsg->iSeverity = pInfo->iSeverity; pMsg->bParseHOSTNAME = 0; getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ - logmsg(pri, pMsg, flags); /* some time, CHKiRet() will work here, too [today NOT!] */ + logmsg(pMsg, flags); /* some time, CHKiRet() will work here, too [today NOT!] */ finalize_it: RETiRet; } -- cgit v1.2.3 From 722e691af737862b32515fd5644feb33547eff8f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 13 Feb 2008 08:14:47 +0000 Subject: - introduced a new, more powerful, message submission interface submitMsg() in additon to logmsg() - a first, rough implementation of imfile that is able to read files (but does not persist or handle rotation or whatever) --- plugins/imfile/imfile.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index d37df02d..3f266a43 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -36,6 +36,7 @@ #include "module-template.h" /* generic module interface code - very important, read it! */ #include "srUtils.h" /* some utility functions */ #include "msg.h" +#include "stream.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -49,7 +50,6 @@ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ * prefix in order not to conflict with other modules or rsyslogd itself (also see comment * at file header). */ -/* static int imtemplateWhateverVar = 0; */ typedef struct fileInfo_s { uchar *pszFileName; @@ -58,7 +58,7 @@ typedef struct fileInfo_s { int64 offsLast; /* offset last read from */ int iFacility; int iSeverity; - int fd; /*its file descriptor (-1 if closed) */ + strm_t *pStrm; /* its stream (NULL if not assigned) */ } fileInfo_t; @@ -85,23 +85,22 @@ typedef struct _instanceData { /* enqueue the read file line as a message */ -static rsRetVal enqLine(fileInfo_t *pInfo, uchar *pLine) +static rsRetVal enqLine(fileInfo_t *pInfo, rsCStrObj *cstrLine) { DEFiRet; msg_t *pMsg; - int flags = 0; - int pri; CHKiRet(msgConstruct(&pMsg)); - MsgSetUxTradMsg(pMsg, (char*)pLine); - MsgSetRawMsg(pMsg, (char*)pLine); + MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); + MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); + MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetHOSTNAME(pMsg, LocalHostName); MsgSetTAG(pMsg, (char*)pInfo->pszTag); pMsg->iFacility = pInfo->iFacility; pMsg->iSeverity = pInfo->iSeverity; pMsg->bParseHOSTNAME = 0; getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ - logmsg(pMsg, flags); /* some time, CHKiRet() will work here, too [today NOT!] */ + CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; } @@ -111,20 +110,26 @@ finalize_it: static rsRetVal pollFile(fileInfo_t *pThis) { DEFiRet; - uchar *pszLine; + rsCStrObj *pCStr; int bAllNewLinesRead; /* set to 1 if all new lines are read */ - if(pThis->fd == -1) { + if(pThis->pStrm == NULL) { /* open file */ + CHKiRet(strmConstruct(&pThis->pStrm)); + CHKiRet(strmSettOperationsMode(pThis->pStrm, STREAMMODE_READ)); + CHKiRet(strmSetsType(pThis->pStrm, STREAMTYPE_FILE_SINGLE)); + CHKiRet(strmSetFName(pThis->pStrm, pThis->pszFileName, strlen((char*) pThis->pszFileName))); + CHKiRet(strmConstructFinalize(pThis->pStrm)); /* move to offset */ } bAllNewLinesRead = 0; while(!bAllNewLinesRead) { /* do read file, put pointer to file line in pszLine */ + CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); /* do the magic ;) */ - CHKiRet(enqLine(pThis, pszLine)); + CHKiRet(enqLine(pThis, pCStr)); } /* save the offset back to structure! */ @@ -243,7 +248,6 @@ ENDwillRun * module-specific config directive. */ BEGINafterRun - /* place any variables needed here */ CODESTARTafterRun /* loop through file array and close everything that's open */ @@ -314,16 +318,19 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a /* add a new monitor */ -static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) +static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute__((unused)) *pNewVal) { DEFiRet; fileInfo_t *pThis; +RUNLOG_VAR("%d", iFilPtr); if(iFilPtr < MAX_INPUT_FILES) { pThis = &files[iFilPtr]; ++iFilPtr; + /* TODO: check for strdup() NULL return */ pThis->pszFileName = (uchar*) strdup((char*) pszFileName); pThis->pszTag = (uchar*) strdup((char*) pszFileTag); + pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; pThis->offsLast = 0; -- cgit v1.2.3 From 18bea60667f4ced5ac65e91fbd7c7a00ba22b319 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 13 Feb 2008 09:39:21 +0000 Subject: added ability to monitor file accross rotation --- plugins/imfile/imfile.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 3f266a43..44832d67 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -117,7 +117,7 @@ static rsRetVal pollFile(fileInfo_t *pThis) /* open file */ CHKiRet(strmConstruct(&pThis->pStrm)); CHKiRet(strmSettOperationsMode(pThis->pStrm, STREAMMODE_READ)); - CHKiRet(strmSetsType(pThis->pStrm, STREAMTYPE_FILE_SINGLE)); + CHKiRet(strmSetsType(pThis->pStrm, STREAMTYPE_FILE_MONITOR)); CHKiRet(strmSetFName(pThis->pStrm, pThis->pszFileName, strlen((char*) pThis->pszFileName))); CHKiRet(strmConstructFinalize(pThis->pStrm)); /* move to offset */ @@ -200,7 +200,7 @@ CODESTARTrunInput pollFile(&files[i]); } - srSleep(1,0); + srSleep(3, 0); /* ------------------------------------------------------------------------------------------ * * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ @@ -328,9 +328,12 @@ RUNLOG_VAR("%d", iFilPtr); pThis = &files[iFilPtr]; ++iFilPtr; /* TODO: check for strdup() NULL return */ - pThis->pszFileName = (uchar*) strdup((char*) pszFileName); - pThis->pszTag = (uchar*) strdup((char*) pszFileTag); - pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); + if(pszFileName != NULL) + pThis->pszFileName = (uchar*) strdup((char*) pszFileName); + if(pszFileTag != NULL) + pThis->pszTag = (uchar*) strdup((char*) pszFileTag); + if(pszStateFile != NULL) + pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; pThis->offsLast = 0; -- cgit v1.2.3 From de1f787307066bea620b3d6631ac68ebf657d561 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 13 Feb 2008 11:44:59 +0000 Subject: - fixed a race condition in DoDie() - cosmetic issue in debugging mode, could not happen in production - added the ability to persist current read location for the file monitor --- plugins/imfile/imfile.c | 122 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 105 insertions(+), 17 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 44832d67..f9c7d0ed 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -25,11 +25,13 @@ * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" /* this is for autotools and always must be the first include */ +#include #include #include #include #include #include /* do NOT remove: will soon be done by the module generation macros */ +#include /* do NOT remove: will soon be done by the module generation macros */ #include "rsyslog.h" /* error codes etc... */ #include "syslogd.h" #include "cfsysline.h" /* access to config file objects */ @@ -106,33 +108,83 @@ finalize_it: } -/* poll a file, need to check file rollover etc. open file if not open */ -static rsRetVal pollFile(fileInfo_t *pThis) +/* try to open a file. This involves checking if there is a status file and, + * if so, reading it in. Processing continues from the last know location. + */ +static rsRetVal +openFile(fileInfo_t *pThis) { DEFiRet; - rsCStrObj *pCStr; - int bAllNewLinesRead; /* set to 1 if all new lines are read */ + strm_t *psSF = NULL; + uchar pszSFNam[MAXFNAME]; + size_t lenSFNam; + struct stat stat_buf; + + /* Construct file name */ + lenSFNam = snprintf((char*)pszSFNam, sizeof(pszSFNam) / sizeof(uchar), "%s/%s", + (char*) glblGetWorkDir(), (char*)pThis->pszStateFile); + + /* check if the file exists */ + if(stat((char*) pszSFNam, &stat_buf) == -1) { + if(errno == ENOENT) { + dbgoprint((obj_t*) pThis, "clean startup, no .si file found\n"); + ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); + } else { + dbgoprint((obj_t*) pThis, "error %d trying to access .si file\n", errno); + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + } - if(pThis->pStrm == NULL) { - /* open file */ + /* If we reach this point, we have a .si file */ + + CHKiRet(strmConstruct(&psSF)); + CHKiRet(strmSettOperationsMode(psSF, STREAMMODE_READ)); + CHKiRet(strmSetsType(psSF, STREAMTYPE_FILE_SINGLE)); + CHKiRet(strmSetFName(psSF, pszSFNam, lenSFNam)); + CHKiRet(strmConstructFinalize(psSF)); + + /* read back in the object */ + CHKiRet(objDeserialize(&pThis->pStrm, OBJstrm, psSF, NULL, pThis)); + + CHKiRet(strmSeekCurrOffs(pThis->pStrm)); + + /* OK, we could successfully read the file, so we now can request that it be + * deleted when we are done with the persisted information. + */ + // TODO: do we need this functionality? psSF->bNeedDelSF = 1; + +finalize_it: + if(psSF != NULL) + strmDestruct(&psSF); + + if(iRet != RS_RET_OK) { + dbgoprint((obj_t*) pThis, "error %d reading .si file - can not read persisted info (not necessarily an error)\n", iRet); CHKiRet(strmConstruct(&pThis->pStrm)); CHKiRet(strmSettOperationsMode(pThis->pStrm, STREAMMODE_READ)); CHKiRet(strmSetsType(pThis->pStrm, STREAMTYPE_FILE_MONITOR)); CHKiRet(strmSetFName(pThis->pStrm, pThis->pszFileName, strlen((char*) pThis->pszFileName))); CHKiRet(strmConstructFinalize(pThis->pStrm)); - /* move to offset */ } - bAllNewLinesRead = 0; - while(!bAllNewLinesRead) { - /* do read file, put pointer to file line in pszLine */ - CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); + RETiRet; +} + + +/* poll a file, need to check file rollover etc. open file if not open */ +static rsRetVal pollFile(fileInfo_t *pThis) +{ + DEFiRet; + rsCStrObj *pCStr; - /* do the magic ;) */ - CHKiRet(enqLine(pThis, pCStr)); + if(pThis->pStrm == NULL) { + CHKiRet(openFile(pThis)); /* open file */ } - /* save the offset back to structure! */ + /* loop below will be exited when strmReadLine() returns EOF */ + while(1) { + CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); + CHKiRet(enqLine(pThis, pCStr)); /* process line */ + } finalize_it: RETiRet; @@ -232,6 +284,39 @@ finalize_it: ENDwillRun + +/* This function persists information for a specific file being monitored. + * To do so, it simply persists the stream object. We do NOT abort on error + * iRet as that makes matters worse (at least we can try persisting the others...). + * rgerhards, 2008-02-13 + */ +static rsRetVal +persistStrmState(fileInfo_t *pInfo) +{ + DEFiRet; + strm_t *psSF = NULL; /* state file (stream) */ + + ASSERT(pInfo != NULL); + +dbgprintf("persistStrmState: dir %s, file %s\n", glblGetWorkDir(), pInfo->pszStateFile); + /* TODO: create a function persistObj in obj.c? */ + CHKiRet(strmConstruct(&psSF)); + CHKiRet(strmSetDir(psSF, glblGetWorkDir(), strlen((char*)glblGetWorkDir()))); + CHKiRet(strmSettOperationsMode(psSF, STREAMMODE_WRITE)); + CHKiRet(strmSetiAddtlOpenFlags(psSF, O_TRUNC)); + CHKiRet(strmSetsType(psSF, STREAMTYPE_FILE_SINGLE)); + CHKiRet(strmSetFName(psSF, pInfo->pszStateFile, strlen((char*) pInfo->pszStateFile))); + CHKiRet(strmConstructFinalize(psSF)); + + CHKiRet(strmSerialize(pInfo->pStrm, psSF)); + + CHKiRet(strmDestruct(&psSF)); + +finalize_it: + RETiRet; +} + + /* This function is called by the framework after runInput() has been terminated. It * shall free any resources and prepare the module for unload. * @@ -248,13 +333,16 @@ ENDwillRun * module-specific config directive. */ BEGINafterRun + int i; CODESTARTafterRun /* loop through file array and close everything that's open */ - /* somehow persist the file arry information, at least the offset! Must be - * able to get back up an rolling even when the order of files inside the - * array changes (think of config changes!). + /* persist file state information. We do NOT abort on error iRet as that makes + * matters worse (at least we can try persisting the others...). */ + for(i = 0 ; i < iFilPtr ; ++i) { + persistStrmState(&files[i]); + } ENDafterRun -- cgit v1.2.3 From 1b0bb1e8168d5b9e8ca5f535a29726e636bbf584 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 13 Feb 2008 11:54:36 +0000 Subject: some cleanup --- plugins/imfile/imfile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index f9c7d0ed..ce7134d2 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -148,10 +148,10 @@ openFile(fileInfo_t *pThis) CHKiRet(strmSeekCurrOffs(pThis->pStrm)); - /* OK, we could successfully read the file, so we now can request that it be - * deleted when we are done with the persisted information. + /* OK, we could successfully read the file, so we now can request that it be deleted. + * If we need it again, it will be written on the next shutdown. */ - // TODO: do we need this functionality? psSF->bNeedDelSF = 1; + psSF->bDeleteOnClose = 1; finalize_it: if(psSF != NULL) -- cgit v1.2.3 From d9905a864c1adc4fe8a519ed8d65189645390e59 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 14 Feb 2008 09:19:38 +0000 Subject: - enhanced file monitor doc - implemented $InputFilePollInterval config directive --- plugins/imfile/imfile.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index ce7134d2..b8198a4c 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -68,6 +68,7 @@ typedef struct fileInfo_s { static uchar *pszFileName = NULL; static uchar *pszFileTag = NULL; static uchar *pszStateFile = NULL; +static int iPollInterval = 10; /* number of seconds to sleep when there was no file activity */ static int iFacility; static int iSeverity; @@ -127,10 +128,10 @@ openFile(fileInfo_t *pThis) /* check if the file exists */ if(stat((char*) pszSFNam, &stat_buf) == -1) { if(errno == ENOENT) { - dbgoprint((obj_t*) pThis, "clean startup, no .si file found\n"); + /* currently no object! dbgoprint((obj_t*) pThis, "clean startup, no .si file found\n"); */ ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } else { - dbgoprint((obj_t*) pThis, "error %d trying to access .si file\n", errno); + /* currently no object! dbgoprint((obj_t*) pThis, "error %d trying to access .si file\n", errno); */ ABORT_FINALIZE(RS_RET_IO_ERROR); } } @@ -158,7 +159,6 @@ finalize_it: strmDestruct(&psSF); if(iRet != RS_RET_OK) { - dbgoprint((obj_t*) pThis, "error %d reading .si file - can not read persisted info (not necessarily an error)\n", iRet); CHKiRet(strmConstruct(&pThis->pStrm)); CHKiRet(strmSettOperationsMode(pThis->pStrm, STREAMMODE_READ)); CHKiRet(strmSetsType(pThis->pStrm, STREAMTYPE_FILE_MONITOR)); @@ -252,7 +252,12 @@ CODESTARTrunInput pollFile(&files[i]); } - srSleep(3, 0); +RUNLOG_VAR("%d", iPollInterval); + /* Note: the 10ns additional wait is vitally important. It guards rsyslog against totally + * hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any + * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 + */ + srSleep(iPollInterval, 10); /* ------------------------------------------------------------------------------------------ * * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ @@ -398,6 +403,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a /* set defaults... */ + iPollInterval = 10; iFacility = 12; /* see RFC 3164 for values */ iSeverity = 4; @@ -411,7 +417,6 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute DEFiRet; fileInfo_t *pThis; -RUNLOG_VAR("%d", iFilPtr); if(iFilPtr < MAX_INPUT_FILES) { pThis = &files[iFilPtr]; ++iFilPtr; @@ -453,9 +458,10 @@ CODEmodInit_QueryRegCFSLineHdlr /* use numerical values as of RFC 3164 for the time being... */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrInt, NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilesfacility", 0, eCmdHdlrInt, + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrInt, NULL, &iFacility, STD_LOADABLE_MODULE_ID)); - /* things missing, e.g. polling intervall... */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, + NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, addMonitor, NULL, STD_LOADABLE_MODULE_ID)); -- cgit v1.2.3 From 413aa120019af45ee8c8c51934cbf5df844a3bdd Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 14 Feb 2008 09:32:46 +0000 Subject: error handling and cleanup in imfile --- plugins/imfile/imfile.c | 51 +++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index b8198a4c..ef233f50 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -252,7 +252,6 @@ CODESTARTrunInput pollFile(&files[i]); } -RUNLOG_VAR("%d", iPollInterval); /* Note: the 10ns additional wait is vitally important. It guards rsyslog against totally * hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 @@ -303,7 +302,6 @@ persistStrmState(fileInfo_t *pInfo) ASSERT(pInfo != NULL); -dbgprintf("persistStrmState: dir %s, file %s\n", glblGetWorkDir(), pInfo->pszStateFile); /* TODO: create a function persistObj in obj.c? */ CHKiRet(strmConstruct(&psSF)); CHKiRet(strmSetDir(psSF, glblGetWorkDir(), strlen((char*)glblGetWorkDir()))); @@ -324,29 +322,16 @@ finalize_it: /* This function is called by the framework after runInput() has been terminated. It * shall free any resources and prepare the module for unload. - * - * So it is important that runInput() keeps track of what needs to be cleaned up. - * Objects to think about are files (must be closed), network connections, threads (must - * be stopped and joined) and memory (must be freed). Of course, there are a myriad - * of other things, so use your own judgement what you need to do. - * - * Another important chore of this function is to persist whatever state the module - * needs to persist. Unfortunately, there is currently no standard way of doing that. - * Future version of the module interface will probably support it, but that doesn't - * help you right at the moment. In general, it is suggested that anything that needs - * to be persisted is saved in a file, whose name and location is passed in by a - * module-specific config directive. */ BEGINafterRun int i; CODESTARTafterRun - /* loop through file array and close everything that's open */ - - /* persist file state information. We do NOT abort on error iRet as that makes + /* Close files and persist file state information. We do NOT abort on error iRet as that makes * matters worse (at least we can try persisting the others...). */ for(i = 0 ; i < iFilPtr ; ++i) { persistStrmState(&files[i]); + strmDestruct(&(files[i].pStrm)); } ENDafterRun @@ -404,8 +389,8 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a /* set defaults... */ iPollInterval = 10; - iFacility = 12; /* see RFC 3164 for values */ - iSeverity = 4; + iFacility = 16; /* local0, as of RFC 3164 */ + iSeverity = 5; /* notice, as of rfc 3164 */ RETiRet; } @@ -419,20 +404,40 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute if(iFilPtr < MAX_INPUT_FILES) { pThis = &files[iFilPtr]; - ++iFilPtr; /* TODO: check for strdup() NULL return */ - if(pszFileName != NULL) + if(pszFileName == NULL) { + logerror("imfile error: no file name given, file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } else { pThis->pszFileName = (uchar*) strdup((char*) pszFileName); - if(pszFileTag != NULL) + } + + if(pszFileTag != NULL) { + logerror("imfile error: no tag value given , file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } else { pThis->pszTag = (uchar*) strdup((char*) pszFileTag); - if(pszStateFile != NULL) + } + + if(pszStateFile != NULL) { + logerror("imfile error: not state file name given, file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } else { pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); + } + pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; pThis->offsLast = 0; } else { logerror("Too many file monitors configured - ignoring this one"); + ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); } + +finalize_it: + if(iRet == RS_RET_OK) + ++iFilPtr; /* we got a new file to monitor */ + RETiRet; } -- cgit v1.2.3 From 5e747be2d0bd05f1c075a2e12bfad56844ddc7d1 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 14 Feb 2008 10:03:44 +0000 Subject: - improved file polling algorithm for more rapid file data delivery - some more cleanup --- plugins/imfile/imfile.c | 56 ++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 26 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index ef233f50..46d8af51 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -30,8 +30,8 @@ #include #include #include +#include #include /* do NOT remove: will soon be done by the module generation macros */ -#include /* do NOT remove: will soon be done by the module generation macros */ #include "rsyslog.h" /* error codes etc... */ #include "syslogd.h" #include "cfsysline.h" /* access to config file objects */ @@ -47,17 +47,10 @@ MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ /* Module static data */ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ -/* Here, define whatever static data is needed. Is it suggested that static variables only are - * used (not externally visible). If you need externally visible variables, make sure you use a - * prefix in order not to conflict with other modules or rsyslogd itself (also see comment - * at file header). - */ - typedef struct fileInfo_s { uchar *pszFileName; uchar *pszTag; uchar *pszStateFile; /* file in which state between runs is to be stored */ - int64 offsLast; /* offset last read from */ int iFacility; int iSeverity; strm_t *pStrm; /* its stream (NULL if not assigned) */ @@ -72,7 +65,7 @@ static int iPollInterval = 10; /* number of seconds to sleep when there was no f static int iFacility; static int iSeverity; -static int iFilPtr = 0; +static int iFilPtr = 0; /* number of files to be monitored; pointer to next free spot during config */ #define MAX_INPUT_FILES 100 static fileInfo_t files[MAX_INPUT_FILES]; @@ -83,8 +76,6 @@ static fileInfo_t files[MAX_INPUT_FILES]; typedef struct _instanceData { } instanceData; -/* config settings */ - /* enqueue the read file line as a message */ @@ -171,11 +162,13 @@ finalize_it: /* poll a file, need to check file rollover etc. open file if not open */ -static rsRetVal pollFile(fileInfo_t *pThis) +static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) { DEFiRet; rsCStrObj *pCStr; + ASSERT(pbHadFileData != NULL); + if(pThis->pStrm == NULL) { CHKiRet(openFile(pThis)); /* open file */ } @@ -183,6 +176,7 @@ static rsRetVal pollFile(fileInfo_t *pThis) /* loop below will be exited when strmReadLine() returns EOF */ while(1) { CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); + *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pThis, pCStr)); /* process line */ } @@ -230,16 +224,24 @@ inputModuleCleanup(void __attribute__((unused)) *arg) * so would end module processing and rsyslog would NOT reschedule the module. If * you exit from this function, you violate the interface specification! * - * So how is it terminated? When it is time to terminate, rsyslog actually cancels - * the threads. This may sound scary, but is not. There is a cancel cleanup handler - * defined (the function directly above). See comments there for specifics. - * - * runInput is always called on a single thread. If the module neees multiple threads, - * it is free to create them. HOWEVER, it must make sure that any threads created - * are killed and joined in the cancel cleanup handler. + * We go through all files and remember if at least one had data. If so, we do + * another run (until no data was present in any file). Then we sleep for + * PollInterval seconds and restart the whole process. This ensures that as + * long as there is some data present, it will be processed at the fastest + * possible pace - probably important for busy systmes. If we monitor just a + * single file, the algorithm is slightly modified. In that case, the sleep + * hapens immediately. The idea here is that if we have just one file, we + * returned from the file processer because that file had no additional data. + * So even if we found some lines, it is highly unlikely to find a new one + * just now. Trying it would result in a performance-costly additional try + * which in the very, very vast majority of cases will never find any new + * lines. + * On spamming the main queue: keep in mind that it will automatically rate-limit + * ourselfes if we begin to overrun it. So we really do not need to care here. */ BEGINrunInput int i; + int bHadFileData; /* were there at least one file with data during this run? */ CODESTARTrunInput /* ------------------------------------------------------------------------------------------ * * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ @@ -248,11 +250,14 @@ CODESTARTrunInput /* END no-touch zone * * ------------------------------------------------------------------------------------------ */ - for(i = 0 ; i < iFilPtr ; ++i) { - pollFile(&files[i]); - } + do { + bHadFileData = 0; + for(i = 0 ; i < iFilPtr ; ++i) { + pollFile(&files[i], &bHadFileData); + } + } while(iFilPtr > 1 && bHadFileData == 1); /* waring: do...while()! */ - /* Note: the 10ns additional wait is vitally important. It guards rsyslog against totally + /* Note: the additional 10ns wait is vitally important. It guards rsyslog against totally * hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 */ @@ -412,14 +417,14 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute pThis->pszFileName = (uchar*) strdup((char*) pszFileName); } - if(pszFileTag != NULL) { + if(pszFileTag == NULL) { logerror("imfile error: no tag value given , file monitor can not be created"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { pThis->pszTag = (uchar*) strdup((char*) pszFileTag); } - if(pszStateFile != NULL) { + if(pszStateFile == NULL) { logerror("imfile error: not state file name given, file monitor can not be created"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { @@ -428,7 +433,6 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; - pThis->offsLast = 0; } else { logerror("Too many file monitors configured - ignoring this one"); ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); -- cgit v1.2.3 From 52b6b6f2211718101e43de05e5292f555e8198a8 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 14 Feb 2008 15:43:50 +0000 Subject: - added new facility and severity syntaxes to cfsysline handler - implemented $InputFileFacility config directive - implemented $InputFileSeverity config directive --- plugins/imfile/imfile.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 46d8af51..47df37f3 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -62,8 +62,8 @@ static uchar *pszFileName = NULL; static uchar *pszFileTag = NULL; static uchar *pszStateFile = NULL; static int iPollInterval = 10; /* number of seconds to sleep when there was no file activity */ -static int iFacility; -static int iSeverity; +static int iFacility = 128; /* local0 */ +static int iSeverity = 5; /* notice, as of rfc 3164 */ static int iFilPtr = 0; /* number of files to be monitored; pointer to next free spot during config */ #define MAX_INPUT_FILES 100 @@ -90,8 +90,8 @@ static rsRetVal enqLine(fileInfo_t *pInfo, rsCStrObj *cstrLine) MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetHOSTNAME(pMsg, LocalHostName); MsgSetTAG(pMsg, (char*)pInfo->pszTag); - pMsg->iFacility = pInfo->iFacility; - pMsg->iSeverity = pInfo->iSeverity; + pMsg->iFacility = LOG_FAC(pInfo->iFacility); + pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); pMsg->bParseHOSTNAME = 0; getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ CHKiRet(submitMsg(pMsg)); @@ -394,7 +394,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a /* set defaults... */ iPollInterval = 10; - iFacility = 16; /* local0, as of RFC 3164 */ + iFacility = 128; /* local0 */ iSeverity = 5; /* notice, as of rfc 3164 */ RETiRet; @@ -438,6 +438,8 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); } + CHKiRet(resetConfigVariables((uchar*) "dummy", (void*) pThis)); /* values are both dummies */ + finalize_it: if(iRet == RS_RET_OK) ++iFilPtr; /* we got a new file to monitor */ @@ -464,10 +466,9 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &pszFileTag, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord, NULL, &pszStateFile, STD_LOADABLE_MODULE_ID)); - /* use numerical values as of RFC 3164 for the time being... */ - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrInt, + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrSeverity, NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrInt, + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility, NULL, &iFacility, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); @@ -477,6 +478,5 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit -/* - * vim:set ai: +/* vim:set ai: */ -- cgit v1.2.3 From 013073f1a6f1ed2230feaba0865d0c14212577d0 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 21 Feb 2008 07:00:29 +0000 Subject: changed rsCStrObj name to cstr_t, which is more inline with the rest of rsyslog (now) and also much easier to type --- plugins/imfile/imfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 47df37f3..b3b2f060 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -79,7 +79,7 @@ typedef struct _instanceData { /* enqueue the read file line as a message */ -static rsRetVal enqLine(fileInfo_t *pInfo, rsCStrObj *cstrLine) +static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) { DEFiRet; msg_t *pMsg; @@ -165,7 +165,7 @@ finalize_it: static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) { DEFiRet; - rsCStrObj *pCStr; + cstr_t *pCStr; ASSERT(pbHadFileData != NULL); -- cgit v1.2.3 From 327467c6f685d25621bb33bc3ab746800ba008d2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 27 Feb 2008 09:39:46 +0000 Subject: bugfix: imfile could abort under extreme stress conditions (when it was terminated before it could open all of its to be monitored files) --- plugins/imfile/imfile.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index b3b2f060..ba09ea42 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -332,11 +332,15 @@ BEGINafterRun int i; CODESTARTafterRun /* Close files and persist file state information. We do NOT abort on error iRet as that makes - * matters worse (at least we can try persisting the others...). + * matters worse (at least we can try persisting the others...). Please note that, under stress + * conditions, it may happen that we are terminated before we actuall could open all streams. So + * before we change anything, we need to make sure the stream was open. */ for(i = 0 ; i < iFilPtr ; ++i) { - persistStrmState(&files[i]); - strmDestruct(&(files[i].pStrm)); + if(files[i].pStrm != NULL) { /* stream open? */ + persistStrmState(&files[i]); + strmDestruct(&(files[i].pStrm)); + } } ENDafterRun -- cgit v1.2.3 From bc7d8ccebb0a9e7726a9c85cb10746d7407c28d8 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Mar 2008 10:27:45 +0000 Subject: - changed module interface to support querying obj interface (stage work) - changed module interface version, as the interface change is quite large --- plugins/imfile/imfile.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index ba09ea42..c13e96e9 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -136,7 +136,7 @@ openFile(fileInfo_t *pThis) CHKiRet(strmConstructFinalize(psSF)); /* read back in the object */ - CHKiRet(objDeserialize(&pThis->pStrm, OBJstrm, psSF, NULL, pThis)); + CHKiRet(objDeserialize(&pThis->pStrm, "strm", psSF, NULL, pThis)); CHKiRet(strmSeekCurrOffs(pThis->pStrm)); @@ -462,19 +462,20 @@ finalize_it: */ BEGINmodInit() CODESTARTmodInit - *ipIFVersProvided = 1; /* interface spec version this module is written to (currently always 1) */ + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, + + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, NULL, &pszFileTag, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord, + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord, NULL, &pszStateFile, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrSeverity, + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrSeverity, NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility, + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility, NULL, &iFacility, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, -- cgit v1.2.3 From 545346e697fe930b8b7b9bd0ede47890b26a4832 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 5 Mar 2008 10:30:06 +0000 Subject: - changed modules.c calling conventions to be interface-based - moved module loader from conf.c to module.c, where it belongs - made the necessary plumbing to auto-load library modules - upgraded debug system to include iRet in function exit message - changed module interface so that instances need only to be supported by output plugins (if we actually need them for input plugins, we can always add it again...) - milestone: first implementation of library modules (but do not get unloaded on exit/hup so far) --- plugins/imfile/imfile.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index c13e96e9..14d6cf3f 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -69,13 +69,6 @@ static int iFilPtr = 0; /* number of files to be monitored; pointer to next fre #define MAX_INPUT_FILES 100 static fileInfo_t files[MAX_INPUT_FILES]; -/* instanceData must be defined to keep the framework happy, but it currently - * is of no practical use. This may change in later revisions of the plugin - * interface. - */ -typedef struct _instanceData { -} instanceData; - /* enqueue the read file line as a message */ @@ -349,16 +342,6 @@ ENDafterRun * In general, they need to be present, but you do NOT need to provide * any code here. */ -BEGINfreeInstance -CODESTARTfreeInstance -ENDfreeInstance - - -BEGINdbgPrintInstInfo -CODESTARTdbgPrintInstInfo -ENDdbgPrintInstInfo - - BEGINmodExit CODESTARTmodExit ENDmodExit -- cgit v1.2.3 From 213e0b596205626214891fb46e1a780af7f26a8b Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 5 Mar 2008 10:39:12 +0000 Subject: bugfix: omfile used invalid obj-call (newly introduced bug) --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 14d6cf3f..ef452bc5 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -129,7 +129,7 @@ openFile(fileInfo_t *pThis) CHKiRet(strmConstructFinalize(psSF)); /* read back in the object */ - CHKiRet(objDeserialize(&pThis->pStrm, "strm", psSF, NULL, pThis)); + CHKiRet(obj.Deserialize(&pThis->pStrm, (uchar*) "strm", psSF, NULL, pThis)); CHKiRet(strmSeekCurrOffs(pThis->pStrm)); -- cgit v1.2.3 From 24b02dc831889986211600a75572737e733ef9d8 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 5 Mar 2008 14:53:25 +0000 Subject: - extracted logerror*() family of functions from syslogd, made them their own class and converted to new object calling conventions (interface-based) - converted gss-misc into a loadable library module --- plugins/imfile/imfile.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index ef452bc5..aa866a6d 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -39,6 +39,7 @@ #include "srUtils.h" /* some utility functions */ #include "msg.h" #include "stream.h" +#include "errmsg.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -46,6 +47,7 @@ MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ /* Module static data */ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ +DEFobjCurrIf(errmsg) typedef struct fileInfo_s { uchar *pszFileName; @@ -278,7 +280,7 @@ ENDrunInput BEGINwillRun CODESTARTwillRun if(iFilPtr == 0) { - logerror("No files configured to be monitored"); + errmsg.LogError(NO_ERRCODE, "No files configured to be monitored"); ABORT_FINALIZE(RS_RET_NO_RUN); } @@ -398,21 +400,21 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute pThis = &files[iFilPtr]; /* TODO: check for strdup() NULL return */ if(pszFileName == NULL) { - logerror("imfile error: no file name given, file monitor can not be created"); + errmsg.LogError(NO_ERRCODE, "imfile error: no file name given, file monitor can not be created"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { pThis->pszFileName = (uchar*) strdup((char*) pszFileName); } if(pszFileTag == NULL) { - logerror("imfile error: no tag value given , file monitor can not be created"); + errmsg.LogError(NO_ERRCODE, "imfile error: no tag value given , file monitor can not be created"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { pThis->pszTag = (uchar*) strdup((char*) pszFileTag); } if(pszStateFile == NULL) { - logerror("imfile error: not state file name given, file monitor can not be created"); + errmsg.LogError(NO_ERRCODE, "imfile error: not state file name given, file monitor can not be created"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); @@ -421,7 +423,7 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; } else { - logerror("Too many file monitors configured - ignoring this one"); + errmsg.LogError(NO_ERRCODE, "Too many file monitors configured - ignoring this one"); ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); } @@ -447,6 +449,7 @@ BEGINmodInit() CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); -- cgit v1.2.3 From 1560e84ff87dafd0d8b4fef3294a7a412e95b1c3 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 5 Mar 2008 16:37:16 +0000 Subject: moved date/time handling functions to their own object (2nd pass) --- plugins/imfile/imfile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index aa866a6d..243004ab 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -40,6 +40,7 @@ #include "msg.h" #include "stream.h" #include "errmsg.h" +#include "datetime.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -48,6 +49,7 @@ MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ /* Module static data */ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ DEFobjCurrIf(errmsg) +DEFobjCurrIf(datetime) typedef struct fileInfo_s { uchar *pszFileName; @@ -88,7 +90,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); pMsg->bParseHOSTNAME = 0; - getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ + datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; @@ -450,6 +452,7 @@ CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); -- cgit v1.2.3 From 24fd07ebe66c56430ca8a752ad1703d29c2f9da4 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 6 Mar 2008 09:59:35 +0000 Subject: (tried to) fix logerror() call under BSD (but can not yet compile, so this may be an error...) --- plugins/imfile/imfile.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 243004ab..c65fc436 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -32,6 +32,9 @@ #include #include #include /* do NOT remove: will soon be done by the module generation macros */ +#ifdef HAVE_SYS_STAT_H +# include +#endif #include "rsyslog.h" /* error codes etc... */ #include "syslogd.h" #include "cfsysline.h" /* access to config file objects */ -- cgit v1.2.3 From 7bd24b3576dc085db1c15d40428a238809a912c1 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 12 Mar 2008 08:20:23 +0000 Subject: bugfix: rsyslogd segfaulted when imfile read an empty line - thanks to Johnny Tan for an excellent bug report --- plugins/imfile/imfile.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index c65fc436..b431fbbc 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -81,20 +81,25 @@ static fileInfo_t files[MAX_INPUT_FILES]; */ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) { - DEFiRet; - msg_t *pMsg; - - CHKiRet(msgConstruct(&pMsg)); - MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); - MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); - MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); - MsgSetHOSTNAME(pMsg, LocalHostName); - MsgSetTAG(pMsg, (char*)pInfo->pszTag); - pMsg->iFacility = LOG_FAC(pInfo->iFacility); - pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); - pMsg->bParseHOSTNAME = 0; - datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ - CHKiRet(submitMsg(pMsg)); + DEFiRet; + msg_t *pMsg; + + if(rsCStrLen(cstrLine) == 0) { + /* we do not process empty lines */ + FINALIZE; + } + + CHKiRet(msgConstruct(&pMsg)); + MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); + MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); + MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); + MsgSetHOSTNAME(pMsg, LocalHostName); + MsgSetTAG(pMsg, (char*)pInfo->pszTag); + pMsg->iFacility = LOG_FAC(pInfo->iFacility); + pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); + pMsg->bParseHOSTNAME = 0; + datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ + CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; } -- cgit v1.2.3 From fdfcb2a8f953cc91abbe628366e3f5474a101670 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Mar 2008 11:04:36 +0000 Subject: added advanced flow control for congestion cases (mode depending on message source and its capablity to be delayed without bad side effects) --- plugins/imfile/imfile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index b431fbbc..91f90cc3 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -90,6 +90,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) } CHKiRet(msgConstruct(&pMsg)); + MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); -- cgit v1.2.3 From 38362e127f7b7b836332bf17097dbbae71bbe810 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Mar 2008 16:41:32 +0000 Subject: bugfix: memory leak in imfile --- plugins/imfile/imfile.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 91f90cc3..ea1b03ad 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -77,7 +77,8 @@ static int iFilPtr = 0; /* number of files to be monitored; pointer to next fre static fileInfo_t files[MAX_INPUT_FILES]; -/* enqueue the read file line as a message +/* enqueue the read file line as a message. The provided string is + * not freed - thuis must be done by the caller. */ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) { @@ -171,7 +172,7 @@ finalize_it: static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) { DEFiRet; - cstr_t *pCStr; + cstr_t *pCStr = NULL; ASSERT(pbHadFileData != NULL); @@ -184,9 +185,14 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pThis, pCStr)); /* process line */ + rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */ } finalize_it: + if(pCStr != NULL) { + rsCStrDestruct(&pCStr); + } + RETiRet; } -- cgit v1.2.3 From 06ffec1c3f9e566993d372cc686c8ae7307c5de0 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 20 Mar 2008 09:31:05 +0000 Subject: bugfix: fixed some minor memory leaks --- plugins/imfile/imfile.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index ea1b03ad..a6e019d6 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -408,11 +408,13 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a /* add a new monitor */ -static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar __attribute__((unused)) *pNewVal) +static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) { DEFiRet; fileInfo_t *pThis; + free(pNewVal); /* we do not need it, but we must free it! */ + if(iFilPtr < MAX_INPUT_FILES) { pThis = &files[iFilPtr]; /* TODO: check for strdup() NULL return */ -- cgit v1.2.3 From 94e32990ee01bc7622909f40f0839bc4516cd56d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 27 Mar 2008 14:58:53 +0000 Subject: fixed memory leaks in stream class and imfile --- plugins/imfile/imfile.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index a6e019d6..162cab9f 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -168,6 +168,17 @@ finalize_it: } +/* The following is a cancel cleanup handler for strmReadLine(). It is necessary in case + * strmReadLine() is cancelled while processing the stream. -- rgerhards, 2008-03-27 + */ +static void pollFileCancelCleanup(void *pArg) +{ + BEGINfunc; + cstr_t **ppCStr = (cstr_t**) pArg; + if(*ppCStr != NULL) + rsCStrDestruct(ppCStr); + ENDfunc; +} /* poll a file, need to check file rollover etc. open file if not open */ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) { @@ -180,6 +191,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) CHKiRet(openFile(pThis)); /* open file */ } + pthread_cleanup_push(pollFileCancelCleanup, &pCStr); /* loop below will be exited when strmReadLine() returns EOF */ while(1) { CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); @@ -187,6 +199,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) CHKiRet(enqLine(pThis, pCStr)); /* process line */ rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */ } + pthread_cleanup_pop(0); finalize_it: if(pCStr != NULL) { @@ -333,6 +346,9 @@ persistStrmState(fileInfo_t *pInfo) CHKiRet(strmDestruct(&psSF)); finalize_it: + if(psSF != NULL) + strmDestruct(&psSF); + RETiRet; } -- cgit v1.2.3 From 890f782323849b2ae01cd705312d54a4a0e348fe Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 11 Apr 2008 17:33:13 +0200 Subject: some cleanup --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 162cab9f..61b50d06 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -95,7 +95,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); - MsgSetHOSTNAME(pMsg, LocalHostName); + MsgSetHOSTNAME(pMsg, (char*)LocalHostName); MsgSetTAG(pMsg, (char*)pInfo->pszTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); -- cgit v1.2.3 From 9030b96c7b0b1b44915ff13384bc2ccbeeaf0626 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sat, 12 Apr 2008 16:55:04 +0200 Subject: implemented high precision timestamps for the kernel log. Thanks to Michael Biebl for pointing out that the kernel log did not have them. --- plugins/imfile/imfile.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 162cab9f..54669641 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -379,6 +379,9 @@ ENDafterRun */ BEGINmodExit CODESTARTmodExit + /* release objects we used */ + objRelease(datetime, CORE_COMPONENT); + objRelease(errmsg, CORE_COMPONENT); ENDmodExit -- cgit v1.2.3 From d9b0c77d3e719d4c08361e62f3b067228c30f6a9 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 16 Apr 2008 15:27:53 +0200 Subject: some more cleanup reduced dependencies, moved non-runtime files to its own directory except for some whom's status is unclear --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 75e54f04..925d0175 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -36,7 +36,7 @@ # include #endif #include "rsyslog.h" /* error codes etc... */ -#include "syslogd.h" +#include "dirty.h" #include "cfsysline.h" /* access to config file objects */ #include "module-template.h" /* generic module interface code - very important, read it! */ #include "srUtils.h" /* some utility functions */ -- cgit v1.2.3 From 87c936ab65b4381fed35689b38c98f130883d903 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 17 Apr 2008 09:07:12 +0200 Subject: modularization work cleanup + created an abstract class for global data items and moved glblGetWorkDir to it --- plugins/imfile/imfile.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 925d0175..f95f9bc4 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -43,6 +43,7 @@ #include "msg.h" #include "stream.h" #include "errmsg.h" +#include "glbl.h" #include "datetime.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -52,6 +53,7 @@ MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ /* Module static data */ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ DEFobjCurrIf(errmsg) +DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) typedef struct fileInfo_s { @@ -121,7 +123,7 @@ openFile(fileInfo_t *pThis) /* Construct file name */ lenSFNam = snprintf((char*)pszSFNam, sizeof(pszSFNam) / sizeof(uchar), "%s/%s", - (char*) glblGetWorkDir(), (char*)pThis->pszStateFile); + (char*) glbl.GetWorkDir(), (char*)pThis->pszStateFile); /* check if the file exists */ if(stat((char*) pszSFNam, &stat_buf) == -1) { @@ -334,7 +336,7 @@ persistStrmState(fileInfo_t *pInfo) /* TODO: create a function persistObj in obj.c? */ CHKiRet(strmConstruct(&psSF)); - CHKiRet(strmSetDir(psSF, glblGetWorkDir(), strlen((char*)glblGetWorkDir()))); + CHKiRet(strmSetDir(psSF, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir()))); CHKiRet(strmSettOperationsMode(psSF, STREAMMODE_WRITE)); CHKiRet(strmSetiAddtlOpenFlags(psSF, O_TRUNC)); CHKiRet(strmSetsType(psSF, STREAMTYPE_FILE_SINGLE)); @@ -381,6 +383,7 @@ BEGINmodExit CODESTARTmodExit /* release objects we used */ objRelease(datetime, CORE_COMPONENT); + objRelease(glbl, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); ENDmodExit @@ -488,6 +491,7 @@ CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, -- cgit v1.2.3 From e1791996b81b486e53a36ec753c3bb595f671983 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 17 Apr 2008 10:58:30 +0200 Subject: moved host/domain-name related variables to global data pool --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index f95f9bc4..a5f1cc8f 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -97,7 +97,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); - MsgSetHOSTNAME(pMsg, (char*)LocalHostName); + MsgSetHOSTNAME(pMsg, (char*)glbl.GetLocalHostName()); MsgSetTAG(pMsg, (char*)pInfo->pszTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); -- cgit v1.2.3 From b711a34a075cf3979f48937f8af8b05030644e82 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 23 Jun 2008 11:29:47 +0200 Subject: disabled compile warnings caused by third-party libraries --- plugins/imfile/imfile.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index a5f1cc8f..d4a332eb 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -181,7 +181,10 @@ static void pollFileCancelCleanup(void *pArg) rsCStrDestruct(ppCStr); ENDfunc; } + + /* poll a file, need to check file rollover etc. open file if not open */ +#pragma GCC diagnostic ignored "-Wempty-body" static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) { DEFiRet; @@ -210,6 +213,7 @@ finalize_it: RETiRet; } +#pragma GCC diagnostic warning "-Wempty-body" /* This function is the cancel cleanup handler. It is called when rsyslog decides the @@ -266,6 +270,7 @@ inputModuleCleanup(void __attribute__((unused)) *arg) * On spamming the main queue: keep in mind that it will automatically rate-limit * ourselfes if we begin to overrun it. So we really do not need to care here. */ +#pragma GCC diagnostic ignored "-Wempty-body" BEGINrunInput int i; int bHadFileData; /* were there at least one file with data during this run? */ @@ -298,6 +303,7 @@ CODESTARTrunInput pthread_cleanup_pop(0); /* just for completeness, but never called... */ RETiRet; /* use it to make sure the housekeeping is done! */ ENDrunInput +#pragma GCC diagnostic warning "-Wempty-body" /* END no-touch zone * * ------------------------------------------------------------------------------------------ */ -- cgit v1.2.3 From 3f6c73a8b7ff2c6d9c931876d823f2b4ef6bbea2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 27 Jun 2008 12:52:45 +0200 Subject: added (internal) error codes to error messages Also added redirector to web description of error codes closes bug http://bugzilla.adiscon.com/show_bug.cgi?id=20 --- plugins/imfile/imfile.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index d4a332eb..dbdf6b94 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -318,7 +318,7 @@ ENDrunInput BEGINwillRun CODESTARTwillRun if(iFilPtr == 0) { - errmsg.LogError(NO_ERRCODE, "No files configured to be monitored"); + errmsg.LogError(0, RS_RET_NO_RUN, "No files configured to be monitored"); ABORT_FINALIZE(RS_RET_NO_RUN); } @@ -447,21 +447,21 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis = &files[iFilPtr]; /* TODO: check for strdup() NULL return */ if(pszFileName == NULL) { - errmsg.LogError(NO_ERRCODE, "imfile error: no file name given, file monitor can not be created"); + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no file name given, file monitor can not be created"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { pThis->pszFileName = (uchar*) strdup((char*) pszFileName); } if(pszFileTag == NULL) { - errmsg.LogError(NO_ERRCODE, "imfile error: no tag value given , file monitor can not be created"); + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no tag value given , file monitor can not be created"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { pThis->pszTag = (uchar*) strdup((char*) pszFileTag); } if(pszStateFile == NULL) { - errmsg.LogError(NO_ERRCODE, "imfile error: not state file name given, file monitor can not be created"); + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: not state file name given, file monitor can not be created"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); @@ -470,7 +470,7 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; } else { - errmsg.LogError(NO_ERRCODE, "Too many file monitors configured - ignoring this one"); + errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, "Too many file monitors configured - ignoring this one"); ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); } -- cgit v1.2.3 From 7b456ce548030ff362d3a2be04b1e5c2c89e0dcb Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 14 Aug 2008 11:19:02 +0200 Subject: bugfix: imfile could cause a segfault upon rsyslogd HUP and termination Thanks to lperr for an excellent bug report that helped detect this problem. --- plugins/imfile/imfile.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 75e54f04..6b7f516e 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -182,8 +182,9 @@ static void pollFileCancelCleanup(void *pArg) /* poll a file, need to check file rollover etc. open file if not open */ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) { - DEFiRet; cstr_t *pCStr = NULL; + int bMustPopCleanup = 0; + DEFiRet; ASSERT(pbHadFileData != NULL); @@ -192,6 +193,8 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) } pthread_cleanup_push(pollFileCancelCleanup, &pCStr); + bMustPopCleanup = 1; + /* loop below will be exited when strmReadLine() returns EOF */ while(1) { CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); @@ -199,9 +202,11 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) CHKiRet(enqLine(pThis, pCStr)); /* process line */ rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */ } - pthread_cleanup_pop(0); finalize_it: + if(bMustPopCleanup) + pthread_cleanup_pop(0); + if(pCStr != NULL) { rsCStrDestruct(&pCStr); } -- cgit v1.2.3 From 3aa86ed554aeb05c386e99d605ddc220250d35d2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 15 Aug 2008 12:21:26 +0200 Subject: fixed cross-platform compile problem introduced with recent change ...which fixed the imfile segfault issue. --- plugins/imfile/imfile.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 6b7f516e..2df1aaf7 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -183,18 +183,18 @@ static void pollFileCancelCleanup(void *pArg) static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) { cstr_t *pCStr = NULL; - int bMustPopCleanup = 0; DEFiRet; ASSERT(pbHadFileData != NULL); + /* Note: we must do pthread_cleanup_push() immediately, because the POXIS macros + * otherwise do not work if I include the _cleanup_pop() inside an if... -- rgerhards, 2008-08-14 + */ + pthread_cleanup_push(pollFileCancelCleanup, &pCStr); if(pThis->pStrm == NULL) { CHKiRet(openFile(pThis)); /* open file */ } - pthread_cleanup_push(pollFileCancelCleanup, &pCStr); - bMustPopCleanup = 1; - /* loop below will be exited when strmReadLine() returns EOF */ while(1) { CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); @@ -204,8 +204,15 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) } finalize_it: - if(bMustPopCleanup) - pthread_cleanup_pop(0); + /*EMPTY - just to keep the compiler happy, do NOT remove*/; + /* Note: the problem above is that pthread:cleanup_pop() is a macro which + * evaluates to something like "} while(0);". So the code would become + * "finalize_it: }", that is a label without a statement. The C standard does + * not permit this. So we add an empty statement "finalize_it: ; }" and + * everybody is happy. Note that without the ;, an error is reported only + * on some platforms/compiler versions. -- rgerhards, 2008-08-15 + */ + pthread_cleanup_pop(0); if(pCStr != NULL) { rsCStrDestruct(&pCStr); -- cgit v1.2.3 From 262f61d869b95f63b393ae48d683b13e70322478 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 10 Sep 2008 15:59:53 +0200 Subject: added properties "inputname" and "$myhostname" - added message property "inputname", which contains the name of the input (module) that generated it. Presence is depending on suport in each input module (else it is blank). - added system property "$myhostname", which contains the name of the local host as it knows itself. --- plugins/imfile/imfile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 3bc07b9c..e8e10fca 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -94,6 +94,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); + MsgSetInputName(pMsg, "imfile"); MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); -- cgit v1.2.3 From 02bb3c901d9b14e8a08b111dde151f1ed4d2d1da Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 2 Oct 2008 15:52:24 +0200 Subject: consolidated time calls during msg object creation ...this improves performance and consistency and also fixes a bug where subsecond time properties generated by imfile, imklog and internal messages could be slightly inconsistent. --- plugins/imfile/imfile.c | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index e8e10fca..b0211bf6 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -103,7 +103,6 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); pMsg->bParseHOSTNAME = 0; - datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; -- cgit v1.2.3 From aba90e82484118f3568ec51c01de5ba845da589a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 22 May 2009 17:06:52 +0200 Subject: added capability to run multiple tcp listeners (on different ports) Well, actually this and a lot of related things. I improved the testbench so that the new capabilities are automatically tested and also did some general cleanup. The current multiple tcp listener solution will probably receive some further cleanup, too, but looks quite OK so far. I also reviewed the way tcpsrv et all work, in preparation of using this code for imdiag. I need to document the findings, especially as the code is rather complicated "thanks" to the combination of plain tcp and gssapi transport modes. --- plugins/imfile/imfile.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index b0211bf6..92fd30c3 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -45,6 +45,7 @@ #include "errmsg.h" #include "glbl.h" #include "datetime.h" +#include "unicode-helper.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -94,11 +95,11 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); - MsgSetInputName(pMsg, "imfile"); + MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile")); MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); - MsgSetHOSTNAME(pMsg, (char*)glbl.GetLocalHostName()); + MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName()); MsgSetTAG(pMsg, (char*)pInfo->pszTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); -- cgit v1.2.3 From 9e434f19a9baa4a6f411808b5cb6bc22d6a32781 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 4 Jun 2009 12:15:59 +0200 Subject: cleaned up stream class ... ... and also made it callable via an rsyslog interface rather then relying on the OS loader (important if we go for using it inside loadbale modules, which we soon possible will) --- plugins/imfile/imfile.c | 51 ++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 92fd30c3..ff32c857 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -56,6 +56,7 @@ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ DEFobjCurrIf(errmsg) DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) +DEFobjCurrIf(strm) typedef struct fileInfo_s { uchar *pszFileName; @@ -139,16 +140,16 @@ openFile(fileInfo_t *pThis) /* If we reach this point, we have a .si file */ - CHKiRet(strmConstruct(&psSF)); - CHKiRet(strmSettOperationsMode(psSF, STREAMMODE_READ)); - CHKiRet(strmSetsType(psSF, STREAMTYPE_FILE_SINGLE)); - CHKiRet(strmSetFName(psSF, pszSFNam, lenSFNam)); - CHKiRet(strmConstructFinalize(psSF)); + CHKiRet(strm.Construct(&psSF)); + CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_READ)); + CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE)); + CHKiRet(strm.SetFName(psSF, pszSFNam, lenSFNam)); + CHKiRet(strm.ConstructFinalize(psSF)); /* read back in the object */ CHKiRet(obj.Deserialize(&pThis->pStrm, (uchar*) "strm", psSF, NULL, pThis)); - CHKiRet(strmSeekCurrOffs(pThis->pStrm)); + CHKiRet(strm.SeekCurrOffs(pThis->pStrm)); /* OK, we could successfully read the file, so we now can request that it be deleted. * If we need it again, it will be written on the next shutdown. @@ -157,14 +158,14 @@ openFile(fileInfo_t *pThis) finalize_it: if(psSF != NULL) - strmDestruct(&psSF); + strm.Destruct(&psSF); if(iRet != RS_RET_OK) { - CHKiRet(strmConstruct(&pThis->pStrm)); - CHKiRet(strmSettOperationsMode(pThis->pStrm, STREAMMODE_READ)); - CHKiRet(strmSetsType(pThis->pStrm, STREAMTYPE_FILE_MONITOR)); - CHKiRet(strmSetFName(pThis->pStrm, pThis->pszFileName, strlen((char*) pThis->pszFileName))); - CHKiRet(strmConstructFinalize(pThis->pStrm)); + CHKiRet(strm.Construct(&pThis->pStrm)); + CHKiRet(strm.SettOperationsMode(pThis->pStrm, STREAMMODE_READ)); + CHKiRet(strm.SetsType(pThis->pStrm, STREAMTYPE_FILE_MONITOR)); + CHKiRet(strm.SetFName(pThis->pStrm, pThis->pszFileName, strlen((char*) pThis->pszFileName))); + CHKiRet(strm.ConstructFinalize(pThis->pStrm)); } RETiRet; @@ -203,7 +204,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) /* loop below will be exited when strmReadLine() returns EOF */ while(1) { - CHKiRet(strmReadLine(pThis->pStrm, &pCStr)); + CHKiRet(strm.ReadLine(pThis->pStrm, &pCStr)); *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pThis, pCStr)); /* process line */ rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */ @@ -354,21 +355,21 @@ persistStrmState(fileInfo_t *pInfo) ASSERT(pInfo != NULL); /* TODO: create a function persistObj in obj.c? */ - CHKiRet(strmConstruct(&psSF)); - CHKiRet(strmSetDir(psSF, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir()))); - CHKiRet(strmSettOperationsMode(psSF, STREAMMODE_WRITE)); - CHKiRet(strmSetiAddtlOpenFlags(psSF, O_TRUNC)); - CHKiRet(strmSetsType(psSF, STREAMTYPE_FILE_SINGLE)); - CHKiRet(strmSetFName(psSF, pInfo->pszStateFile, strlen((char*) pInfo->pszStateFile))); - CHKiRet(strmConstructFinalize(psSF)); + CHKiRet(strm.Construct(&psSF)); + CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir()))); + CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE)); + CHKiRet(strm.SetiAddtlOpenFlags(psSF, O_TRUNC)); + CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE)); + CHKiRet(strm.SetFName(psSF, pInfo->pszStateFile, strlen((char*) pInfo->pszStateFile))); + CHKiRet(strm.ConstructFinalize(psSF)); - CHKiRet(strmSerialize(pInfo->pStrm, psSF)); + CHKiRet(strm.Serialize(pInfo->pStrm, psSF)); - CHKiRet(strmDestruct(&psSF)); + CHKiRet(strm.Destruct(&psSF)); finalize_it: if(psSF != NULL) - strmDestruct(&psSF); + strm.Destruct(&psSF); RETiRet; } @@ -388,7 +389,7 @@ CODESTARTafterRun for(i = 0 ; i < iFilPtr ; ++i) { if(files[i].pStrm != NULL) { /* stream open? */ persistStrmState(&files[i]); - strmDestruct(&(files[i].pStrm)); + strm.Destruct(&(files[i].pStrm)); } } ENDafterRun @@ -401,6 +402,7 @@ ENDafterRun BEGINmodExit CODESTARTmodExit /* release objects we used */ + objRelease(strm, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); @@ -512,6 +514,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); + CHKiRet(objUse(strm, CORE_COMPONENT)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); -- cgit v1.2.3 From 76da7f9f4e3dc900046a1956153d10532f2b1ae0 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 4 Jun 2009 15:59:37 +0200 Subject: added $OMFileIOBufferSize config directive and plumbing --- plugins/imfile/imfile.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index ff32c857..42c70539 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -357,8 +357,7 @@ persistStrmState(fileInfo_t *pInfo) /* TODO: create a function persistObj in obj.c? */ CHKiRet(strm.Construct(&psSF)); CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir()))); - CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE)); - CHKiRet(strm.SetiAddtlOpenFlags(psSF, O_TRUNC)); + CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE_TRUNC)); CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetFName(psSF, pInfo->pszStateFile, strlen((char*) pInfo->pszStateFile))); CHKiRet(strm.ConstructFinalize(psSF)); -- cgit v1.2.3 From 015d17ca70e81ad998e32cdfeed3cd925fd7dedc Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 16 Jun 2009 08:46:45 +0200 Subject: some performance optimizations - saved gettimeofday() calls in imtcp (and increased reception buffer) - somewhat optimized stringbuf.c - some other optimizations --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 92fd30c3..e3882ce5 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -95,7 +95,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile")); + MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); -- cgit v1.2.3 From 74b2b24f508be90d20961304d5e3cce648f3eb7c Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 16 Jun 2009 12:31:27 +0200 Subject: removed long-obsoleted property UxTradMsg ... as well as some cleanup (some commented-out code is left to support UxTradMsg again is someone really complains ;)). --- plugins/imfile/imfile.c | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index e3882ce5..927cb82e 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -96,7 +96,6 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); - MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName()); -- cgit v1.2.3 From 8628312396b1535c41124e499d292f4d1e77d955 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 18 Jun 2009 13:22:21 +0200 Subject: cleaned up/optimized raw message handling in msg object --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 86270e2d..bdd222c4 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -97,7 +97,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); - MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); + MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName()); MsgSetTAG(pMsg, (char*)pInfo->pszTag); -- cgit v1.2.3 From 2f86678c577ee469852ffae35123c4a90b12d214 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 18 Jun 2009 14:30:21 +0200 Subject: optimized TAG handling in msg object --- plugins/imfile/imfile.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index bdd222c4..0dabc757 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -61,6 +61,7 @@ DEFobjCurrIf(strm) typedef struct fileInfo_s { uchar *pszFileName; uchar *pszTag; + size_t lenTag; uchar *pszStateFile; /* file in which state between runs is to be stored */ int iFacility; int iSeverity; @@ -100,7 +101,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName()); - MsgSetTAG(pMsg, (char*)pInfo->pszTag); + MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); pMsg->bParseHOSTNAME = 0; @@ -471,6 +472,7 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } else { pThis->pszTag = (uchar*) strdup((char*) pszFileTag); + pThis->lenTag = ustrlen(pThis->pszTag); } if(pszStateFile == NULL) { -- cgit v1.2.3 From 2de4964affabc1ccf61bc72426a468fc871a54d0 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 18 Jun 2009 16:51:40 +0200 Subject: optimized handling of MSG part in msg object WARNING: currently, message repeation processing is disabled, must be reenabled (but prefer to do some other tests first) --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 0dabc757..0f5f49dc 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -99,7 +99,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); - MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); + MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName()); MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); -- cgit v1.2.3 From 662ad3e4bf8dbd317d18aa1afcbf3e8b9e424506 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 23 Jun 2009 16:32:29 +0200 Subject: optimized hostname processing --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 0f5f49dc..631d02ff 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -100,7 +100,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ - MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName()); + MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); -- cgit v1.2.3 From de84a12f8a5f140c0f7b8e00f4cac92ef13cd866 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 29 Jun 2009 16:53:26 +0200 Subject: introduced the idea of detached properties some things inside the message can be used over a large number of messages and need to to be allocated and re-written every time. I now begin to implement this as a "prop_t" object, first use for the inputName. Some input modules are already converted, some others to go. Will do a little performance check on the new method before I go further. Also, this commit has some cleanup and a few bug fixes that prevented compiliation in debug mode (I overlooked this as I did not compile for debug, what I normally do, and the automatted test also does not do that) --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 631d02ff..fdd0c5f0 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -97,7 +97,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); -- cgit v1.2.3 From e397c34d2a6c7c1e4c116fd2363cb173e32eb2a2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 30 Jun 2009 15:21:15 +0200 Subject: finished transition to using inputName property ... plus some celanup and adding minor missing functionality (the rule debug info again tell the property name, not just number). --- plugins/imfile/imfile.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index fdd0c5f0..7c588f90 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -46,6 +46,7 @@ #include "glbl.h" #include "datetime.h" #include "unicode-helper.h" +#include "prop.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -57,6 +58,7 @@ DEFobjCurrIf(errmsg) DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) DEFobjCurrIf(strm) +DEFobjCurrIf(prop) typedef struct fileInfo_s { uchar *pszFileName; @@ -81,6 +83,7 @@ static int iFilPtr = 0; /* number of files to be monitored; pointer to next fre #define MAX_INPUT_FILES 100 static fileInfo_t files[MAX_INPUT_FILES]; +static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ /* enqueue the read file line as a message. The provided string is * not freed - thuis must be done by the caller. @@ -97,7 +100,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); - MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); + MsgSetInputName(pMsg, pInputName); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); @@ -336,6 +339,11 @@ CODESTARTwillRun ABORT_FINALIZE(RS_RET_NO_RUN); } + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imfile"), sizeof("imfile") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + finalize_it: ENDwillRun @@ -391,6 +399,9 @@ CODESTARTafterRun strm.Destruct(&(files[i].pStrm)); } } + + if(pInputName != NULL) + prop.Destruct(&pInputName); ENDafterRun @@ -405,6 +416,7 @@ CODESTARTmodExit objRelease(datetime, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); ENDmodExit @@ -515,6 +527,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(strm, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); -- cgit v1.2.3 From 05b0c4322bbd7621762dc4b9b3a2e1baeabdaa1f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 13 Oct 2009 07:29:11 +0200 Subject: removed no longer needed msg_t property "bParseHOSTNAME" --- plugins/imfile/imfile.c | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 7c588f90..7cfde940 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -107,7 +107,6 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); - pMsg->bParseHOSTNAME = 0; CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; -- cgit v1.2.3 From 5c0920c159dc76565af344d65d0aa57d62cc389a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 16 Oct 2009 09:24:55 +0200 Subject: cosmetic: cleanup of imfile --- plugins/imfile/imfile.c | 48 +++++++++++++----------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 7cfde940..955d5b14 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -5,7 +5,7 @@ * * Work originally begun on 2008-02-01 by Rainer Gerhards * - * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * Copyright 2008,2009 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -213,7 +213,6 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) } finalize_it: - /*EMPTY - just to keep the compiler happy, do NOT remove*/; /* Note: the problem above is that pthread:cleanup_pop() is a macro which * evaluates to something like "} while(0);". So the code would become * "finalize_it: }", that is a label without a statement. The C standard does @@ -243,27 +242,12 @@ finalize_it: * IMPORTANT: the calling interface of this function can NOT be modified. It actually is * called by pthreads. The provided argument is currently not being used. */ -/* ------------------------------------------------------------------------------------------ * - * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ static void inputModuleCleanup(void __attribute__((unused)) *arg) { BEGINfunc -/* END no-touch zone * - * ------------------------------------------------------------------------------------------ */ - - - - /* so far not needed */ - - - -/* ------------------------------------------------------------------------------------------ * - * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ ENDfunc } -/* END no-touch zone * - * ------------------------------------------------------------------------------------------ */ /* This function is called by the framework to gather the input. The module stays @@ -291,28 +275,22 @@ BEGINrunInput int i; int bHadFileData; /* were there at least one file with data during this run? */ CODESTARTrunInput - /* ------------------------------------------------------------------------------------------ * - * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ pthread_cleanup_push(inputModuleCleanup, NULL); - while(1) { /* endless loop - do NOT break; out of it! */ - /* END no-touch zone * - * ------------------------------------------------------------------------------------------ */ + while(1) { - do { - bHadFileData = 0; - for(i = 0 ; i < iFilPtr ; ++i) { - pollFile(&files[i], &bHadFileData); - } - } while(iFilPtr > 1 && bHadFileData == 1); /* waring: do...while()! */ + do { + bHadFileData = 0; + for(i = 0 ; i < iFilPtr ; ++i) { + pollFile(&files[i], &bHadFileData); + } + } while(iFilPtr > 1 && bHadFileData == 1); /* warning: do...while()! */ - /* Note: the additional 10ns wait is vitally important. It guards rsyslog against totally - * hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any - * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 - */ - srSleep(iPollInterval, 10); + /* Note: the additional 10ns wait is vitally important. It guards rsyslog against totally + * hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any + * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 + */ + srSleep(iPollInterval, 10); - /* ------------------------------------------------------------------------------------------ * - * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ } /*NOTREACHED*/ -- cgit v1.2.3 From 13ca93c27aeabbb3e1e217c05b5aa13e00be2475 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 19 Oct 2009 15:52:53 +0200 Subject: my imfile cleanup was a bit too agressive ;) ... so I moved the one line that some platforms need back in. --- plugins/imfile/imfile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 955d5b14..8a10e26f 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -213,6 +213,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) } finalize_it: + ; /*EMPTY STATEMENT - needed to keep compiler happy - see below! */ /* Note: the problem above is that pthread:cleanup_pop() is a macro which * evaluates to something like "} while(0);". So the code would become * "finalize_it: }", that is a label without a statement. The C standard does -- cgit v1.2.3 From e64cd212432c2cf76245888499461e9c8bf73243 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 21 Jul 2010 18:08:19 +0200 Subject: moving towards scoping inside rsyslog.conf first step: adding object-type specifier to config statement table --- plugins/imfile/imfile.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 8a10e26f..fd15918c 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -508,22 +508,22 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, - NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); + NULL, &pszFileName, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, - NULL, &pszFileTag, STD_LOADABLE_MODULE_ID)); + NULL, &pszFileTag, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord, - NULL, &pszStateFile, STD_LOADABLE_MODULE_ID)); + NULL, &pszStateFile, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrSeverity, - NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); + NULL, &iSeverity, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility, - NULL, &iFacility, STD_LOADABLE_MODULE_ID)); + NULL, &iFacility, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, - NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); + NULL, &iPollInterval, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, - addMonitor, NULL, STD_LOADABLE_MODULE_ID)); + addMonitor, NULL, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, - resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); + resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); ENDmodInit /* vim:set ai: */ -- cgit v1.2.3 From ed9fd3541f07929008a64f5b6ea3bcce70e62c25 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 15 Oct 2010 08:23:29 +0200 Subject: imfile: bug fixes either one or two bugs fixed ;) Definitely a problem where no state file is written when working with relative pathes. Also, some problems with offsets should be fixed for very large files. However, I could not yet experimentally show the issue so it probably needs more verification. --- plugins/imfile/imfile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 8a10e26f..e067014e 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -337,12 +337,15 @@ persistStrmState(fileInfo_t *pInfo) { DEFiRet; strm_t *psSF = NULL; /* state file (stream) */ + size_t lenDir; ASSERT(pInfo != NULL); /* TODO: create a function persistObj in obj.c? */ CHKiRet(strm.Construct(&psSF)); - CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir()))); + lenDir = ustrlen(glbl.GetWorkDir()); + if(lenDir > 0) + CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), lenDir)); CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE_TRUNC)); CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetFName(psSF, pInfo->pszStateFile, strlen((char*) pInfo->pszStateFile))); -- cgit v1.2.3 From 90933057bc2f014fd2124ba7d830652e9b1ead96 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 15 Oct 2010 16:39:10 +0200 Subject: imfile: bugfixes in regard to large files (> 2GB) - bugfix: a couple of problems that imfile had on some platforms, namely Ubuntu (not their fault, but occured there) - bugfix: imfile utilizes 32 bit to track offset. Most importantly, this problem can not experienced on Fedora 64 bit OS (which has 64 bit long's!) --- plugins/imfile/imfile.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 7c588f90..e16f26f8 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -359,12 +359,14 @@ persistStrmState(fileInfo_t *pInfo) { DEFiRet; strm_t *psSF = NULL; /* state file (stream) */ + size_t lenDir; ASSERT(pInfo != NULL); /* TODO: create a function persistObj in obj.c? */ CHKiRet(strm.Construct(&psSF)); - CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir()))); + lenDir = strlen((char*)glbl.GetWorkDir()); + CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), lenDir)); CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE_TRUNC)); CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetFName(psSF, pInfo->pszStateFile, strlen((char*) pInfo->pszStateFile))); -- cgit v1.2.3 From c27a2ab6867897ec379ec1e9afb216c99070b33e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 15 Oct 2010 07:47:31 -0700 Subject: fixed incomplete merge --- plugins/imfile/imfile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index e16f26f8..3981f9f7 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -366,6 +366,7 @@ persistStrmState(fileInfo_t *pInfo) /* TODO: create a function persistObj in obj.c? */ CHKiRet(strm.Construct(&psSF)); lenDir = strlen((char*)glbl.GetWorkDir()); + if(lenDir > 0) CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), lenDir)); CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE_TRUNC)); CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE)); -- cgit v1.2.3 From ffd08f2a6caaaddb86ccbec4206bf560d34fcfd7 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sun, 24 Oct 2010 14:31:12 +0200 Subject: imfile improvements - added the $InputFilePersistStateInterval config directive to imfile - changed imfile so that the state file is never deleted (makes imfile more robust in regard to fatal failures) --- plugins/imfile/imfile.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 3981f9f7..91493bb1 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -67,15 +67,21 @@ typedef struct fileInfo_s { uchar *pszStateFile; /* file in which state between runs is to be stored */ int iFacility; int iSeverity; + int nRecords; /**< How many records did we process before persisting the stream? */ + int iPersistStateInterval; /**< how often should state be persisted? (0=on close only) */ strm_t *pStrm; /* its stream (NULL if not assigned) */ } fileInfo_t; +/* forward definitions */ +static rsRetVal persistStrmState(fileInfo_t *pInfo); + /* config variables */ static uchar *pszFileName = NULL; static uchar *pszFileTag = NULL; static uchar *pszStateFile = NULL; static int iPollInterval = 10; /* number of seconds to sleep when there was no file activity */ +static int iPersistStateInterval = 0; /* how often if state file to be persisted? (default 0->never) */ static int iFacility = 128; /* local0 */ static int iSeverity = 5; /* notice, as of rfc 3164 */ @@ -154,10 +160,9 @@ openFile(fileInfo_t *pThis) CHKiRet(strm.SeekCurrOffs(pThis->pStrm)); - /* OK, we could successfully read the file, so we now can request that it be deleted. - * If we need it again, it will be written on the next shutdown. + /* note: we do not delete the state file, so that the last position remains + * known even in the case that rsyslogd aborts for some reason (like powerfail) */ - psSF->bDeleteOnClose = 1; finalize_it: if(psSF != NULL) @@ -211,6 +216,10 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pThis, pCStr)); /* process line */ rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */ + if(pThis->iPersistStateInterval > 0 && pThis->nRecords++ >= pThis->iPersistStateInterval) { + persistStrmState(pThis); + pThis->nRecords = 0; + } } finalize_it: @@ -244,27 +253,12 @@ finalize_it: * IMPORTANT: the calling interface of this function can NOT be modified. It actually is * called by pthreads. The provided argument is currently not being used. */ -/* ------------------------------------------------------------------------------------------ * - * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ static void inputModuleCleanup(void __attribute__((unused)) *arg) { BEGINfunc -/* END no-touch zone * - * ------------------------------------------------------------------------------------------ */ - - - - /* so far not needed */ - - - -/* ------------------------------------------------------------------------------------------ * - * DO NOT TOUCH the following code - it will soon be part of the module generation macros! */ ENDfunc } -/* END no-touch zone * - * ------------------------------------------------------------------------------------------ */ /* This function is called by the framework to gather the input. The module stays @@ -499,6 +493,9 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; + pThis->iPersistStateInterval = iPersistStateInterval; + pThis->nRecords = 0; + iPersistStateInterval = 0; } else { errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, "Too many file monitors configured - ignoring this one"); ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); @@ -544,6 +541,8 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &iFacility, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt, + NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, addMonitor, NULL, STD_LOADABLE_MODULE_ID)); -- cgit v1.2.3 From 40814bb0307f9d8536b3dc4a28b94f80a361b41d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 27 Oct 2010 10:10:47 +0200 Subject: imfile improvements - added the $InputFilePersistStateInterval config directive to imfile - changed imfile so that the state file is never deleted (makes imfile more robust in regard to fatal failures) --- plugins/imfile/imfile.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 6c2a64de..686fa048 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -47,6 +47,7 @@ #include "datetime.h" #include "unicode-helper.h" #include "prop.h" +#include "stringbuf.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -67,15 +68,21 @@ typedef struct fileInfo_s { uchar *pszStateFile; /* file in which state between runs is to be stored */ int iFacility; int iSeverity; + int nRecords; /**< How many records did we process before persisting the stream? */ + int iPersistStateInterval; /**< how often should state be persisted? (0=on close only) */ strm_t *pStrm; /* its stream (NULL if not assigned) */ } fileInfo_t; +/* forward definitions */ +static rsRetVal persistStrmState(fileInfo_t *pInfo); + /* config variables */ static uchar *pszFileName = NULL; static uchar *pszFileTag = NULL; static uchar *pszStateFile = NULL; static int iPollInterval = 10; /* number of seconds to sleep when there was no file activity */ +static int iPersistStateInterval = 0; /* how often if state file to be persisted? (default 0->never) */ static int iFacility = 128; /* local0 */ static int iSeverity = 5; /* notice, as of rfc 3164 */ @@ -153,10 +160,9 @@ openFile(fileInfo_t *pThis) CHKiRet(strm.SeekCurrOffs(pThis->pStrm)); - /* OK, we could successfully read the file, so we now can request that it be deleted. - * If we need it again, it will be written on the next shutdown. + /* note: we do not delete the state file, so that the last position remains + * known even in the case that rsyslogd aborts for some reason (like powerfail) */ - psSF->bDeleteOnClose = 1; finalize_it: if(psSF != NULL) @@ -210,6 +216,10 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pThis, pCStr)); /* process line */ rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */ + if(pThis->iPersistStateInterval > 0 && pThis->nRecords++ >= pThis->iPersistStateInterval) { + persistStrmState(pThis); + pThis->nRecords = 0; + } } finalize_it: @@ -477,6 +487,7 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; + pThis->iPersistStateInterval = iPersistStateInterval; } else { errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, "Too many file monitors configured - ignoring this one"); ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); @@ -522,6 +533,9 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &iFacility, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt, + + NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, addMonitor, NULL, STD_LOADABLE_MODULE_ID)); -- cgit v1.2.3 From 9813a12789d08a00fa96c11f113cd531c7f2ce7b Mon Sep 17 00:00:00 2001 From: David Lang Date: Tue, 25 Jan 2011 14:24:50 +0100 Subject: enhanced imfile to support multi-line messages Signed-off-by: Rainer Gerhards --- plugins/imfile/imfile.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 8681ac8c..c205f60e 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -71,6 +71,7 @@ typedef struct fileInfo_s { int nRecords; /**< How many records did we process before persisting the stream? */ int iPersistStateInterval; /**< how often should state be persisted? (0=on close only) */ strm_t *pStrm; /* its stream (NULL if not assigned) */ + int readMode; /* which mode to use in ReadMulteLine call? */ } fileInfo_t; @@ -85,6 +86,7 @@ static int iPollInterval = 10; /* number of seconds to sleep when there was no f static int iPersistStateInterval = 0; /* how often if state file to be persisted? (default 0->never) */ static int iFacility = 128; /* local0 */ static int iSeverity = 5; /* notice, as of rfc 3164 */ +static int readMode = 0; /* mode to use for ReadMultiLine call */ static int iFilPtr = 0; /* number of files to be monitored; pointer to next free spot during config */ #define MAX_INPUT_FILES 100 @@ -212,7 +214,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) /* loop below will be exited when strmReadLine() returns EOF */ while(1) { - CHKiRet(strm.ReadLine(pThis->pStrm, &pCStr)); + CHKiRet(strm.ReadLine(pThis->pStrm, &pCStr, pThis->readMode)); *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pThis, pCStr)); /* process line */ rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */ @@ -447,6 +449,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a iPollInterval = 10; iFacility = 128; /* local0 */ iSeverity = 5; /* notice, as of rfc 3164 */ + readMode = 0; RETiRet; } @@ -489,6 +492,7 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis->iFacility = iFacility; pThis->iPersistStateInterval = iPersistStateInterval; pThis->nRecords = 0; + pThis->readMode = readMode; iPersistStateInterval = 0; } else { errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, "Too many file monitors configured - ignoring this one"); @@ -535,6 +539,8 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &iFacility, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilereadmode", 0, eCmdHdlrInt, + NULL, &readMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt, NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ -- cgit v1.2.3 From 2c1021a01f75f5bb3e16b7b952a2d29494943bed Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 10 Feb 2011 18:23:34 +0100 Subject: enhanced imfile to support non-cancel input termination --- plugins/imfile/imfile.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index c205f60e..7f6b9c24 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -213,7 +213,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) } /* loop below will be exited when strmReadLine() returns EOF */ - while(1) { + while(glbl.GetGlobalInputTermState() == 0) { CHKiRet(strm.ReadLine(pThis->pStrm, &pCStr, pThis->readMode)); *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pThis, pCStr)); /* process line */ @@ -289,9 +289,10 @@ BEGINrunInput int bHadFileData; /* were there at least one file with data during this run? */ CODESTARTrunInput pthread_cleanup_push(inputModuleCleanup, NULL); - while(1) { - + while(glbl.GetGlobalInputTermState() == 0) { do { + if(glbl.GetGlobalInputTermState() == 1) + break; /* terminate input! */ bHadFileData = 0; for(i = 0 ; i < iFilPtr ; ++i) { pollFile(&files[i], &bHadFileData); @@ -302,10 +303,10 @@ CODESTARTrunInput * hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 */ - srSleep(iPollInterval, 10); - + if(glbl.GetGlobalInputTermState() == 0) + srSleep(iPollInterval, 10); } - /*NOTREACHED*/ + DBGPRINTF("imfile: terminating upon request of rsyslog core\n"); pthread_cleanup_pop(0); /* just for completeness, but never called... */ RETiRet; /* use it to make sure the housekeeping is done! */ @@ -398,6 +399,13 @@ CODESTARTafterRun ENDafterRun +BEGINisCompatibleWithFeature +CODESTARTisCompatibleWithFeature + if(eFeat == sFEATURENonCancelInputTermination) + iRet = RS_RET_OK; +ENDisCompatibleWithFeature + + /* The following entry points are defined in module-template.h. * In general, they need to be present, but you do NOT need to provide * any code here. @@ -416,6 +424,7 @@ ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES +CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt @@ -527,6 +536,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(strm, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); + DBGPRINTF("imfile: version %s initializing\n", VERSION); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, -- cgit v1.2.3 From f3d354da3e373f9c4890a78e5274a6ba02f1c8cb Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 11 Feb 2011 17:47:30 +0100 Subject: bugfix: very long running actions could prevent shutdown under some circumstances This has now been solved, at least for common situations. --- plugins/imfile/imfile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 7f6b9c24..c71e425e 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -291,13 +291,13 @@ CODESTARTrunInput pthread_cleanup_push(inputModuleCleanup, NULL); while(glbl.GetGlobalInputTermState() == 0) { do { - if(glbl.GetGlobalInputTermState() == 1) - break; /* terminate input! */ bHadFileData = 0; for(i = 0 ; i < iFilPtr ; ++i) { + if(glbl.GetGlobalInputTermState() == 1) + break; /* terminate input! */ pollFile(&files[i], &bHadFileData); } - } while(iFilPtr > 1 && bHadFileData == 1); /* warning: do...while()! */ + } while(iFilPtr > 1 && bHadFileData == 1 && glbl.GetGlobalInputTermState() == 0); /* warning: do...while()! */ /* Note: the additional 10ns wait is vitally important. It guards rsyslog against totally * hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any -- cgit v1.2.3 From 2f1ef6164afa3a91f0bdd92507d0e8d557bea555 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 18 Feb 2011 16:04:50 +0100 Subject: enhance: imfile did not yet support multiple rulesets, now added we do this directly in the beta because a) it does not affect existing functionality and b) one may argue that this missing functionality is close to a bug. --- plugins/imfile/imfile.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index c71e425e..1dd5e65c 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -48,6 +48,7 @@ #include "unicode-helper.h" #include "prop.h" #include "stringbuf.h" +#include "ruleset.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -60,6 +61,7 @@ DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) DEFobjCurrIf(strm) DEFobjCurrIf(prop) +DEFobjCurrIf(ruleset) typedef struct fileInfo_s { uchar *pszFileName; @@ -72,6 +74,7 @@ typedef struct fileInfo_s { int iPersistStateInterval; /**< how often should state be persisted? (0=on close only) */ strm_t *pStrm; /* its stream (NULL if not assigned) */ int readMode; /* which mode to use in ReadMulteLine call? */ + ruleset_t *pRuleset; /* ruleset to bind listener to (use system default if unspecified) */ } fileInfo_t; @@ -87,6 +90,7 @@ static int iPersistStateInterval = 0; /* how often if state file to be persisted static int iFacility = 128; /* local0 */ static int iSeverity = 5; /* notice, as of rfc 3164 */ static int readMode = 0; /* mode to use for ReadMultiLine call */ +static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */ static int iFilPtr = 0; /* number of files to be monitored; pointer to next free spot during config */ #define MAX_INPUT_FILES 100 @@ -116,6 +120,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); + MsgSetRuleset(pMsg, pInfo->pRuleset); CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; @@ -418,6 +423,7 @@ CODESTARTmodExit objRelease(glbl, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); + objRelease(ruleset, CORE_COMPONENT); ENDmodExit @@ -459,6 +465,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a iFacility = 128; /* local0 */ iSeverity = 5; /* notice, as of rfc 3164 */ readMode = 0; + pBindRuleset = NULL; RETiRet; } @@ -502,6 +509,7 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis->iPersistStateInterval = iPersistStateInterval; pThis->nRecords = 0; pThis->readMode = readMode; + pThis->pRuleset = pBindRuleset; iPersistStateInterval = 0; } else { errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, "Too many file monitors configured - ignoring this one"); @@ -517,6 +525,29 @@ finalize_it: RETiRet; } + +/* accept a new ruleset to bind. Checks if it exists and complains, if not */ +static rsRetVal +setRuleset(void __attribute__((unused)) *pVal, uchar *pszName) +{ + ruleset_t *pRuleset; + rsRetVal localRet; + DEFiRet; + + localRet = ruleset.GetRuleset(&pRuleset, pszName); + if(localRet == RS_RET_NOT_FOUND) { + errmsg.LogError(0, NO_ERRCODE, "error: ruleset '%s' not found - ignored", pszName); + } + CHKiRet(localRet); + pBindRuleset = pRuleset; + DBGPRINTF("imfile current bind ruleset %p: '%s'\n", pRuleset, pszName); + +finalize_it: + free(pszName); /* no longer needed */ + RETiRet; +} + + /* modInit() is called once the module is loaded. It must perform all module-wide * initialization tasks. There are also a number of housekeeping tasks that the * framework requires. These are handled by the macros. Please note that the @@ -534,6 +565,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(strm, CORE_COMPONENT)); + CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); DBGPRINTF("imfile: version %s initializing\n", VERSION); @@ -553,6 +585,8 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &readMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt, NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilebindruleset", 0, eCmdHdlrGetWord, + setRuleset, NULL, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, addMonitor, NULL, STD_LOADABLE_MODULE_ID)); -- cgit v1.2.3 From d1eb6e0edc51a78f3209448e800b25eda50340f2 Mon Sep 17 00:00:00 2001 From: Bojan Smojver Date: Wed, 23 Feb 2011 11:25:43 +0100 Subject: added work-around for bug in gtls, which causes fd leak when using TLS The capability has been added for module to specify that they do not like being unloaded. related bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=222 Signed-off-by: Rainer Gerhards --- plugins/imfile/imfile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 1dd5e65c..acb58dad 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -51,6 +51,7 @@ #include "ruleset.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ +MODULE_TYPE_NOKEEP /* defines */ -- cgit v1.2.3 From 804cbee541f24f61be41d6405754bf082da288a0 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 11 Mar 2011 15:45:44 +0100 Subject: bugfix: very minor memory leak in imfile almost cosmetic: leaks a few bytes once during a run -- more a problem for valgrind testing -- not for practical use --- plugins/imfile/imfile.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index de71fb74..0b24d08d 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -294,6 +294,11 @@ BEGINrunInput int i; int bHadFileData; /* were there at least one file with data during this run? */ CODESTARTrunInput + /* free config vars that are still allocated (at this point, we do no longer need them) */ + free(pszFileName); + free(pszFileTag); + free(pszStateFile); + pthread_cleanup_push(inputModuleCleanup, NULL); while(glbl.GetGlobalInputTermState() == 0) { do { -- cgit v1.2.3 From 00771a760bf2603276be906ad168ed50c90bf412 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 14 Mar 2011 12:17:27 +0100 Subject: fixing cosmetic memory leak in imdiag, imfile This had no real consequences, as it happend exactly once during the runtime, so the OS cleaned up. However, it broke the valgrind testbench. --- plugins/imfile/imfile.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index acb58dad..cac3a55d 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -331,6 +331,11 @@ ENDrunInput */ BEGINwillRun CODESTARTwillRun + /* free config variables we do no longer needed */ + free(pszFileName); + free(pszFileTag); + free(pszStateFile); + if(iFilPtr == 0) { errmsg.LogError(0, RS_RET_NO_RUN, "No files configured to be monitored"); ABORT_FINALIZE(RS_RET_NO_RUN); @@ -398,6 +403,9 @@ CODESTARTafterRun persistStrmState(&files[i]); strm.Destruct(&(files[i].pStrm)); } + free(files[i].pszFileName); + free(files[i].pszTag); + free(files[i].pszStateFile); } if(pInputName != NULL) -- cgit v1.2.3 From 8ca7467ed408965b44864b507e734e209d35338a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 14 Mar 2011 14:37:40 +0100 Subject: fixed double-free regerssion, probably caused by last merge --- plugins/imfile/imfile.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 61aa9b4f..37d3136c 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -294,11 +294,6 @@ BEGINrunInput int i; int bHadFileData; /* were there at least one file with data during this run? */ CODESTARTrunInput - /* free config vars that are still allocated (at this point, we do no longer need them) */ - free(pszFileName); - free(pszFileTag); - free(pszStateFile); - pthread_cleanup_push(inputModuleCleanup, NULL); while(glbl.GetGlobalInputTermState() == 0) { do { -- cgit v1.2.3 From 32db6291bc310062cffd3266fc297c7b13c571a7 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 16 Mar 2011 16:59:49 +0100 Subject: backporting patch for clean make distcheck --- plugins/imfile/imfile.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index acb58dad..cac3a55d 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -331,6 +331,11 @@ ENDrunInput */ BEGINwillRun CODESTARTwillRun + /* free config variables we do no longer needed */ + free(pszFileName); + free(pszFileTag); + free(pszStateFile); + if(iFilPtr == 0) { errmsg.LogError(0, RS_RET_NO_RUN, "No files configured to be monitored"); ABORT_FINALIZE(RS_RET_NO_RUN); @@ -398,6 +403,9 @@ CODESTARTafterRun persistStrmState(&files[i]); strm.Destruct(&(files[i].pStrm)); } + free(files[i].pszFileName); + free(files[i].pszTag); + free(files[i].pszStateFile); } if(pInputName != NULL) -- cgit v1.2.3 From b722cd3fe608a0bbf4a6df962f9d5c5e547fdc09 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 19 Apr 2011 12:18:26 +0200 Subject: milestone: ruleset now supports rsconf_t --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 37d3136c..67eebefe 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -543,7 +543,7 @@ setRuleset(void __attribute__((unused)) *pVal, uchar *pszName) rsRetVal localRet; DEFiRet; - localRet = ruleset.GetRuleset(&pRuleset, pszName); + localRet = ruleset.GetRuleset(ourConf, &pRuleset, pszName); if(localRet == RS_RET_NOT_FOUND) { errmsg.LogError(0, NO_ERRCODE, "error: ruleset '%s' not found - ignored", pszName); } -- cgit v1.2.3 From d0d9f823b79c5649dad18cb1d8d7744796ae0907 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 3 May 2011 18:02:18 +0200 Subject: step: put plumbing in place for new input module config system --- plugins/imfile/imfile.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 67eebefe..f3aff1bb 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -83,6 +83,10 @@ typedef struct fileInfo_s { static rsRetVal persistStrmState(fileInfo_t *pInfo); /* config variables */ +typedef struct { + EMPTY_STRUCT; +} modConfData_t; + static uchar *pszFileName = NULL; static uchar *pszFileTag = NULL; static uchar *pszStateFile = NULL; @@ -322,6 +326,31 @@ ENDrunInput * ------------------------------------------------------------------------------------------ */ +BEGINbeginCnfLoad +CODESTARTbeginCnfLoad +ENDbeginCnfLoad + + +BEGINendCnfLoad +CODESTARTendCnfLoad +ENDendCnfLoad + + +BEGINcheckCnf +CODESTARTcheckCnf +ENDcheckCnf + + +BEGINactivateCnf +CODESTARTactivateCnf +ENDactivateCnf + + +BEGINfreeCnf +CODESTARTfreeCnf +ENDfreeCnf + + /* The function is called by rsyslog before runInput() is called. It is a last chance * to set up anything specific. Most importantly, it can be used to tell rsyslog if the * input shall run or not. The idea is that if some config settings (or similiar things) -- cgit v1.2.3 From c0d1334f6e23b1cfb21d302e3a4b32c449c26547 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 5 May 2011 11:36:05 +0200 Subject: step: imtcp moved to new config interface as far as we know that new interface right now ;) --- plugins/imfile/imfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index f3aff1bb..321abbda 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -83,9 +83,9 @@ typedef struct fileInfo_s { static rsRetVal persistStrmState(fileInfo_t *pInfo); /* config variables */ -typedef struct { +struct modConfData_s { EMPTY_STRUCT; -} modConfData_t; +}; static uchar *pszFileName = NULL; static uchar *pszFileTag = NULL; -- cgit v1.2.3 From 503dec99f2e21fba336c989b209fadbf201e6f7e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 20 May 2011 11:30:31 +0200 Subject: imfile is being totally refactored -- add new conf system when done otherwise we may waste a lot of effort... --- plugins/imfile/imfile.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 321abbda..4425c949 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -326,30 +326,6 @@ ENDrunInput * ------------------------------------------------------------------------------------------ */ -BEGINbeginCnfLoad -CODESTARTbeginCnfLoad -ENDbeginCnfLoad - - -BEGINendCnfLoad -CODESTARTendCnfLoad -ENDendCnfLoad - - -BEGINcheckCnf -CODESTARTcheckCnf -ENDcheckCnf - - -BEGINactivateCnf -CODESTARTactivateCnf -ENDactivateCnf - - -BEGINfreeCnf -CODESTARTfreeCnf -ENDfreeCnf - /* The function is called by rsyslog before runInput() is called. It is a last chance * to set up anything specific. Most importantly, it can be used to tell rsyslog if the -- cgit v1.2.3 From 59056371156616274d9970300b3ab02432201422 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 24 May 2011 09:34:14 +0200 Subject: enhanced imfile to support input batching --- plugins/imfile/imfile.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index cac3a55d..415eb137 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -64,6 +64,7 @@ DEFobjCurrIf(strm) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) +#define NUM_MULTISUB 1024 /* max number of submits -- TODO: make configurable */ typedef struct fileInfo_s { uchar *pszFileName; uchar *pszTag; @@ -76,6 +77,7 @@ typedef struct fileInfo_s { strm_t *pStrm; /* its stream (NULL if not assigned) */ int readMode; /* which mode to use in ReadMulteLine call? */ ruleset_t *pRuleset; /* ruleset to bind listener to (use system default if unspecified) */ + multi_submit_t multiSub; } fileInfo_t; @@ -122,7 +124,9 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); MsgSetRuleset(pMsg, pInfo->pRuleset); - CHKiRet(submitMsg(pMsg)); + pInfo->multiSub.ppMsgs[pInfo->multiSub.nElem++] = pMsg; + if(pInfo->multiSub.nElem == pInfo->multiSub.maxElem) + CHKiRet(multiSubmitMsg(&pInfo->multiSub)); finalize_it: RETiRet; } @@ -229,8 +233,13 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) pThis->nRecords = 0; } } + /* NOTE: This is usually not reached due to loop exit via CHKiRet() only! */ finalize_it: + if(pThis->multiSub.nElem > 0) { + /* submit everything that was not yet submitted */ + CHKiRet(multiSubmitMsg(&pThis->multiSub)); + } ; /*EMPTY STATEMENT - needed to keep compiler happy - see below! */ /* Note: the problem above is that pthread:cleanup_pop() is a macro which * evaluates to something like "} while(0);". So the code would become @@ -513,6 +522,9 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); } + CHKmalloc(pThis->multiSub.ppMsgs = MALLOC(NUM_MULTISUB * sizeof(msg_t*))); + pThis->multiSub.maxElem = NUM_MULTISUB; + pThis->multiSub.nElem = 0; pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; pThis->iPersistStateInterval = iPersistStateInterval; -- cgit v1.2.3 From ffdc33e3f178ad85ba5c2c9f7fcee98b743e9d5e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 24 May 2011 10:09:43 +0200 Subject: imfile: added $InputFileMaxLinesAtOnce directive --- plugins/imfile/imfile.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 415eb137..9bc84220 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -72,6 +72,7 @@ typedef struct fileInfo_s { uchar *pszStateFile; /* file in which state between runs is to be stored */ int iFacility; int iSeverity; + int maxLinesAtOnce; int nRecords; /**< How many records did we process before persisting the stream? */ int iPersistStateInterval; /**< how often should state be persisted? (0=on close only) */ strm_t *pStrm; /* its stream (NULL if not assigned) */ @@ -93,6 +94,7 @@ static int iPersistStateInterval = 0; /* how often if state file to be persisted static int iFacility = 128; /* local0 */ static int iSeverity = 5; /* notice, as of rfc 3164 */ static int readMode = 0; /* mode to use for ReadMultiLine call */ +static int maxLinesAtOnce = 10240; /* how many lines to process in a row? */ static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */ static int iFilPtr = 0; /* number of files to be monitored; pointer to next free spot during config */ @@ -210,6 +212,7 @@ static void pollFileCancelCleanup(void *pArg) static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) { cstr_t *pCStr = NULL; + int nProcessed = 0; DEFiRet; ASSERT(pbHadFileData != NULL); @@ -224,7 +227,10 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) /* loop below will be exited when strmReadLine() returns EOF */ while(glbl.GetGlobalInputTermState() == 0) { + if(pThis->maxLinesAtOnce != 0 && nProcessed >= pThis->maxLinesAtOnce) + break; CHKiRet(strm.ReadLine(pThis->pStrm, &pCStr, pThis->readMode)); + ++nProcessed; *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pThis, pCStr)); /* process line */ rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */ @@ -233,7 +239,6 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) pThis->nRecords = 0; } } - /* NOTE: This is usually not reached due to loop exit via CHKiRet() only! */ finalize_it: if(pThis->multiSub.nElem > 0) { @@ -484,6 +489,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a iSeverity = 5; /* notice, as of rfc 3164 */ readMode = 0; pBindRuleset = NULL; + maxLinesAtOnce = 10240; RETiRet; } @@ -527,6 +533,7 @@ static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) pThis->multiSub.nElem = 0; pThis->iSeverity = iSeverity; pThis->iFacility = iFacility; + pThis->maxLinesAtOnce = maxLinesAtOnce; pThis->iPersistStateInterval = iPersistStateInterval; pThis->nRecords = 0; pThis->readMode = readMode; @@ -604,6 +611,8 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilereadmode", 0, eCmdHdlrInt, NULL, &readMode, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilemaxlinesatonce", 0, eCmdHdlrSize, + NULL, &maxLinesAtOnce, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt, NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilebindruleset", 0, eCmdHdlrGetWord, -- cgit v1.2.3 From a7e3afb20b461f608f478e8fca15b02e67d6d9c3 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 20 Jul 2011 10:47:24 +0200 Subject: milestone: added module config names --- plugins/imfile/imfile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 3537d809..8dc618ab 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -52,6 +52,7 @@ MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ MODULE_TYPE_NOKEEP +MODULE_CNFNAME("imfile") /* defines */ -- cgit v1.2.3 From cd5253fa82fdbd7529f76c9cec2130e1ccb210bb Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 7 Oct 2011 11:42:49 +0200 Subject: bugfix: imfile did invalid system call under some circumstances when a file that was to be monitored did not exist BUT the state file actually existed. Mostly a cosmetic issue. Root cause was incomplete error checking in stream.c; so patch may affect other code areas. --- plugins/imfile/imfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index cac3a55d..40a41a98 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -147,10 +147,10 @@ openFile(fileInfo_t *pThis) /* check if the file exists */ if(stat((char*) pszSFNam, &stat_buf) == -1) { if(errno == ENOENT) { - /* currently no object! dbgoprint((obj_t*) pThis, "clean startup, no .si file found\n"); */ + dbgprintf("filemon %p: clean startup, no .si file found\n", pThis); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } else { - /* currently no object! dbgoprint((obj_t*) pThis, "error %d trying to access .si file\n", errno); */ + dbgprintf("filemon %p: error %d trying to access .si file\n", pThis, errno); ABORT_FINALIZE(RS_RET_IO_ERROR); } } -- cgit v1.2.3 From ca39d8e60e569d837f39a9c33e28cf8f0e89f321 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 12 Jan 2012 03:29:19 +0100 Subject: more files moved to ASL 2.0 --- plugins/imfile/imfile.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 91493bb1..a3c671b1 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -5,24 +5,23 @@ * * Work originally begun on 2008-02-01 by Rainer Gerhards * - * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * Copyright 2008-2012 Adiscon GmbH. * * This file is part of rsyslog. * - * Rsyslog is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Rsyslog is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Rsyslog. If not, see . - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. + * 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" /* this is for autotools and always must be the first include */ #include -- cgit v1.2.3 From 9b24152b6ac6af942a62675c6136316fd487b661 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 18 Jan 2012 18:21:08 +0100 Subject: undoing v6.1 config scoping interface, part I The most common files are now changed, more needs to be done. --- plugins/imfile/imfile.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 963c1707..ba8318df 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -578,28 +578,28 @@ CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("imfile: version %s initializing\n", VERSION); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, - NULL, &pszFileName, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, - NULL, &pszFileTag, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + NULL, &pszFileTag, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord, - NULL, &pszStateFile, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + NULL, &pszStateFile, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrSeverity, - NULL, &iSeverity, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility, - NULL, &iFacility, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + NULL, &iFacility, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, - NULL, &iPollInterval, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilereadmode", 0, eCmdHdlrInt, - NULL, &readMode, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + NULL, &readMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt, - NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilebindruleset", 0, eCmdHdlrGetWord, - setRuleset, NULL, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + setRuleset, NULL, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, - addMonitor, NULL, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + addMonitor, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, - resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID, eConfObjGlobal)); + resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit /* vim:set ai: */ -- cgit v1.2.3 From 9a1d7044b9d300dd957a046b79629ddd26a76a2c Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 26 Sep 2012 19:41:59 +0200 Subject: milestone: port imfile to v6 config system --- plugins/imfile/imfile.c | 408 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 273 insertions(+), 135 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 440f5991..c2d0db51 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -81,25 +81,48 @@ typedef struct fileInfo_s { multi_submit_t multiSub; } fileInfo_t; +static struct configSettings_s { + uchar *pszFileName; + uchar *pszFileTag; + uchar *pszStateFile; + uchar *pszBindRuleset; + int iPollInterval; /* number of seconds to sleep when there was no file activity */ + int iPersistStateInterval; /* how often if state file to be persisted? (default 0->never) */ + int iFacility; /* local0 */ + int iSeverity; /* notice, as of rfc 3164 */ + int readMode; /* mode to use for ReadMultiLine call */ + int maxLinesAtOnce; /* how many lines to process in a row? */ + ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ +} cs; + +struct instanceConf_s { + uchar *pszFileName; + uchar *pszTag; + uchar *pszStateFile; + uchar *pszBindRuleset; + int nMultiSub; + int iPersistStateInterval; + int iFacility; + int iSeverity; + int readMode; + int maxLinesAtOnce; + ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ + struct instanceConf_s *next; +}; + /* forward definitions */ static rsRetVal persistStrmState(fileInfo_t *pInfo); +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal); /* config variables */ struct modConfData_s { - EMPTY_STRUCT; + rsconf_t *pConf; /* our overall config object */ + instanceConf_t *root, *tail; + sbool configSetViaV2Method; }; - -static uchar *pszFileName = NULL; -static uchar *pszFileTag = NULL; -static uchar *pszStateFile = NULL; -static int iPollInterval = 10; /* number of seconds to sleep when there was no file activity */ -static int iPersistStateInterval = 0; /* how often if state file to be persisted? (default 0->never) */ -static int iFacility = 128; /* local0 */ -static int iSeverity = 5; /* notice, as of rfc 3164 */ -static int readMode = 0; /* mode to use for ReadMultiLine call */ -static int maxLinesAtOnce = 10240; /* how many lines to process in a row? */ -static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */ +static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ +static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */ static int iFilPtr = 0; /* number of files to be monitored; pointer to next free spot during config */ #define MAX_INPUT_FILES 100 @@ -107,6 +130,8 @@ static fileInfo_t files[MAX_INPUT_FILES]; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ +#include "im-helper.h" /* must be included AFTER the type definitions! */ + /* enqueue the read file line as a message. The provided string is * not freed - thuis must be done by the caller. */ @@ -268,6 +293,210 @@ finalize_it: #pragma GCC diagnostic warning "-Wempty-body" +/* create input instance, set default paramters, and + * add it to the list of instances. + */ +static rsRetVal +createInstance(instanceConf_t **pinst) +{ + instanceConf_t *inst; + DEFiRet; + CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + inst->next = NULL; + inst->pBindRuleset = NULL; + + inst->pszBindRuleset = NULL; + inst->pszFileName = NULL; + inst->pszTag = NULL; + inst->pszStateFile = NULL; + inst->nMultiSub = NUM_MULTISUB; + inst->iSeverity = 5; + inst->iFacility = 128; + inst->maxLinesAtOnce = 10240; + inst->iPersistStateInterval = 0; + inst->readMode = 0; + + /* node created, let's add to config */ + if(loadModConf->tail == NULL) { + loadModConf->tail = loadModConf->root = inst; + } else { + loadModConf->tail->next = inst; + loadModConf->tail = inst; + } + + *pinst = inst; +finalize_it: + RETiRet; +} + + +/* add a new monitor */ +static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) +{ + instanceConf_t *inst; + DEFiRet; + + if(cs.pszFileName == NULL) { + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no file name given, file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } + if(cs.pszFileTag == NULL) { + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no tag value given , file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } + if(cs.pszStateFile == NULL) { + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: not state file name given, file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } + + CHKiRet(createInstance(&inst)); + if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) { + inst->pszBindRuleset = NULL; + } else { + CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset)); + } + inst->pszFileName = (uchar*) strdup((char*) cs.pszFileName); + inst->pszTag = (uchar*) strdup((char*) cs.pszFileTag); + inst->pszStateFile = (uchar*) strdup((char*) cs.pszStateFile); + inst->nMultiSub = NUM_MULTISUB; + inst->iSeverity = cs.iSeverity; + inst->iFacility = cs.iFacility; + inst->maxLinesAtOnce = cs.maxLinesAtOnce; + inst->iPersistStateInterval = cs.iPersistStateInterval; + inst->readMode = cs.readMode; + + /* reset legacy system */ + cs.iPersistStateInterval = 0; + resetConfigVariables(NULL, NULL); /* values are both dummies */ + +finalize_it: + free(pNewVal); /* we do not need it, but we must free it! */ + RETiRet; +} + + +/* This function is called when a new listener (monitor) shall be added. */ +static inline rsRetVal +addListner(instanceConf_t *inst) +{ + DEFiRet; + fileInfo_t *pThis; + + if(iFilPtr < MAX_INPUT_FILES) { + pThis = &files[iFilPtr]; + //TODO: optimize, save strdup? + pThis->pszFileName = (uchar*) strdup((char*) inst->pszFileName); + pThis->pszTag = (uchar*) strdup((char*) inst->pszTag); + pThis->lenTag = ustrlen(pThis->pszTag); + pThis->pszStateFile = (uchar*) strdup((char*) inst->pszStateFile); + + CHKmalloc(pThis->multiSub.ppMsgs = MALLOC(inst->nMultiSub * sizeof(msg_t*))); + pThis->multiSub.maxElem = inst->nMultiSub; + pThis->multiSub.nElem = 0; + pThis->iSeverity = inst->iSeverity; + pThis->iFacility = inst->iFacility; + pThis->maxLinesAtOnce = inst->maxLinesAtOnce; + pThis->iPersistStateInterval = inst->iPersistStateInterval; + pThis->readMode = inst->readMode; + pThis->pRuleset = inst->pBindRuleset; + pThis->nRecords = 0; + } else { + errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, + "Too many file monitors configured - ignoring %s", + inst->pszFileName); + ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); + } + ++iFilPtr; /* we got a new file to monitor */ + + resetConfigVariables(NULL, NULL); /* values are both dummies */ +finalize_it: + RETiRet; +} + +BEGINbeginCnfLoad +CODESTARTbeginCnfLoad + loadModConf = pModConf; + pModConf->pConf = pConf; + /* init our settings */ + loadModConf->configSetViaV2Method = 0; + /* init legacy config vars */ + cs.pszFileName = NULL; + cs.pszFileTag = NULL; + cs.pszStateFile = NULL; + cs.iPollInterval = 10; + cs.iPersistStateInterval = 0; + cs.iFacility = 128; + cs.iSeverity = 5; + cs.readMode = 0; + cs.maxLinesAtOnce = 10240; + cs.pBindRuleset = NULL; +ENDbeginCnfLoad + + +BEGINendCnfLoad +CODESTARTendCnfLoad + if(!loadModConf->configSetViaV2Method) { + /* persist module-specific settings from legacy config system */ + } + +//finalize_it: + loadModConf = NULL; /* done loading */ + /* free legacy config vars */ + free(cs.pszFileName); + free(cs.pszFileTag); + free(cs.pszStateFile); +ENDendCnfLoad + + +BEGINcheckCnf + instanceConf_t *inst; +CODESTARTcheckCnf + for(inst = pModConf->root ; inst != NULL ; inst = inst->next) { + std_checkRuleset(pModConf, inst); + } + if(pModConf->root == NULL) { + errmsg.LogError(0, RS_RET_NO_LISTNERS, + "imfile: no files configured to be monitored - " + "no input will be gathered"); + iRet = RS_RET_NO_LISTNERS; + } +ENDcheckCnf + + +/* note: we do access files AFTER we have dropped privileges. This is + * intentional, user must make sure the files have the right permissions. + */ +BEGINactivateCnf + instanceConf_t *inst; +CODESTARTactivateCnf + runModConf = pModConf; + for(inst = runModConf->root ; inst != NULL ; inst = inst->next) { + addListner(inst); + } + /* if we could not set up any listners, there is no point in running... */ + //if(lcnfRoot == NULL) { + if(iFilPtr == 0) { + errmsg.LogError(0, NO_ERRCODE, "imfile: no file monitors could be started, " + "input not activated.\n"); + ABORT_FINALIZE(RS_RET_NO_RUN); + } +finalize_it: +ENDactivateCnf + + +BEGINfreeCnf + instanceConf_t *inst, *del; +CODESTARTfreeCnf + for(inst = pModConf->root ; inst != NULL ; ) { + // free(inst->pszBindPort); + del = inst; + inst = inst->next; + free(del); + } +ENDfreeCnf + + + /* This function is the cancel cleanup handler. It is called when rsyslog decides the * module must be stopped, what most probably happens during shutdown of rsyslogd. When * this function is called, the runInput() function (below) is already terminated - somewhere @@ -328,7 +557,7 @@ CODESTARTrunInput * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 */ if(glbl.GetGlobalInputTermState() == 0) - srSleep(iPollInterval, 10); + srSleep(cs.iPollInterval, 10); } DBGPRINTF("imfile: terminating upon request of rsyslog core\n"); @@ -350,16 +579,6 @@ ENDrunInput */ BEGINwillRun CODESTARTwillRun - /* free config variables we do no longer needed */ - free(pszFileName); - free(pszFileTag); - free(pszStateFile); - - if(iFilPtr == 0) { - errmsg.LogError(0, RS_RET_NO_RUN, "No files configured to be monitored"); - ABORT_FINALIZE(RS_RET_NO_RUN); - } - /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imfile"), sizeof("imfile") - 1)); @@ -458,6 +677,7 @@ ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES +CODEqueryEtryPt_STD_CONF2_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt @@ -468,119 +688,37 @@ ENDqueryEtryPt * but in general this is not necessary. Once runInput() has been called, this * function here is never again called. */ -static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +static rsRetVal +resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) { DEFiRet; - if(pszFileName != NULL) { - free(pszFileName); - pszFileName = NULL; - } - - if(pszFileTag != NULL) { - free(pszFileTag); - pszFileTag = NULL; - } - - if(pszStateFile != NULL) { - free(pszFileTag); - pszFileTag = NULL; - } - + free(cs.pszFileName); + cs.pszFileName = NULL; + free(cs.pszFileTag); + cs.pszFileTag = NULL; + free(cs.pszFileTag); + cs.pszFileTag = NULL; /* set defaults... */ - iPollInterval = 10; - iFacility = 128; /* local0 */ - iSeverity = 5; /* notice, as of rfc 3164 */ - readMode = 0; - pBindRuleset = NULL; - maxLinesAtOnce = 10240; + cs.iPollInterval = 10; + cs.iFacility = 128; /* local0 */ + cs.iSeverity = 5; /* notice, as of rfc 3164 */ + cs.readMode = 0; + cs.pBindRuleset = NULL; + cs.maxLinesAtOnce = 10240; RETiRet; } - -/* add a new monitor */ -static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) +static inline void +std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) { - DEFiRet; - fileInfo_t *pThis; - - free(pNewVal); /* we do not need it, but we must free it! */ - - if(iFilPtr < MAX_INPUT_FILES) { - pThis = &files[iFilPtr]; - /* TODO: check for strdup() NULL return */ - if(pszFileName == NULL) { - errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no file name given, file monitor can not be created"); - ABORT_FINALIZE(RS_RET_CONFIG_ERROR); - } else { - pThis->pszFileName = (uchar*) strdup((char*) pszFileName); - } - - if(pszFileTag == NULL) { - errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no tag value given , file monitor can not be created"); - ABORT_FINALIZE(RS_RET_CONFIG_ERROR); - } else { - pThis->pszTag = (uchar*) strdup((char*) pszFileTag); - pThis->lenTag = ustrlen(pThis->pszTag); - } - - if(pszStateFile == NULL) { - errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: not state file name given, file monitor can not be created"); - ABORT_FINALIZE(RS_RET_CONFIG_ERROR); - } else { - pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); - } - - CHKmalloc(pThis->multiSub.ppMsgs = MALLOC(NUM_MULTISUB * sizeof(msg_t*))); - pThis->multiSub.maxElem = NUM_MULTISUB; - pThis->multiSub.nElem = 0; - pThis->iSeverity = iSeverity; - pThis->iFacility = iFacility; - pThis->maxLinesAtOnce = maxLinesAtOnce; - pThis->iPersistStateInterval = iPersistStateInterval; - pThis->nRecords = 0; - pThis->readMode = readMode; - pThis->pRuleset = pBindRuleset; - iPersistStateInterval = 0; - } else { - errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, "Too many file monitors configured - ignoring this one"); - ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); - } - - CHKiRet(resetConfigVariables((uchar*) "dummy", (void*) pThis)); /* values are both dummies */ - -finalize_it: - if(iRet == RS_RET_OK) - ++iFilPtr; /* we got a new file to monitor */ - - RETiRet; + errmsg.LogError(0, NO_ERRCODE, "imfile: ruleset '%s' for %s not found - " + "using default ruleset instead", inst->pszBindRuleset, + inst->pszFileName); } - -/* accept a new ruleset to bind. Checks if it exists and complains, if not */ -static rsRetVal -setRuleset(void __attribute__((unused)) *pVal, uchar *pszName) -{ - ruleset_t *pRuleset; - rsRetVal localRet; - DEFiRet; - - localRet = ruleset.GetRuleset(ourConf, &pRuleset, pszName); - if(localRet == RS_RET_NOT_FOUND) { - errmsg.LogError(0, NO_ERRCODE, "error: ruleset '%s' not found - ignored", pszName); - } - CHKiRet(localRet); - pBindRuleset = pRuleset; - DBGPRINTF("imfile current bind ruleset %p: '%s'\n", pRuleset, pszName); - -finalize_it: - free(pszName); /* no longer needed */ - RETiRet; -} - - /* modInit() is called once the module is loaded. It must perform all module-wide * initialization tasks. There are also a number of housekeeping tasks that the * framework requires. These are handled by the macros. Please note that the @@ -603,28 +741,28 @@ CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("imfile: version %s initializing\n", VERSION); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, - NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); + NULL, &cs.pszFileName, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, - NULL, &pszFileTag, STD_LOADABLE_MODULE_ID)); + NULL, &cs.pszFileTag, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord, - NULL, &pszStateFile, STD_LOADABLE_MODULE_ID)); + NULL, &cs.pszStateFile, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrSeverity, - NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); + NULL, &cs.iSeverity, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility, - NULL, &iFacility, STD_LOADABLE_MODULE_ID)); + NULL, &cs.iFacility, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, - NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); + NULL, &cs.iPollInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilereadmode", 0, eCmdHdlrInt, - NULL, &readMode, STD_LOADABLE_MODULE_ID)); + NULL, &cs.readMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilemaxlinesatonce", 0, eCmdHdlrSize, - NULL, &maxLinesAtOnce, STD_LOADABLE_MODULE_ID)); + NULL, &cs.maxLinesAtOnce, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt, - NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID)); + NULL, &cs.iPersistStateInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilebindruleset", 0, eCmdHdlrGetWord, - setRuleset, NULL, STD_LOADABLE_MODULE_ID)); + NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, - addMonitor, NULL, STD_LOADABLE_MODULE_ID)); + addInstance, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit -- cgit v1.2.3 From 24c348bf5cb5fecfcb8e02518cece57d72dbdd58 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 27 Sep 2012 07:51:22 +0200 Subject: imfile: implement support for input() --- plugins/imfile/imfile.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index c2d0db51..4edd550d 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -130,6 +130,25 @@ static fileInfo_t files[MAX_INPUT_FILES]; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ +/* input instance parameters */ +static struct cnfparamdescr inppdescr[] = { + { "file", eCmdHdlrString, CNFPARAM_REQUIRED }, + { "statefile", eCmdHdlrString, CNFPARAM_REQUIRED }, + { "tag", eCmdHdlrString, CNFPARAM_REQUIRED }, + { "severity", eCmdHdlrSeverity, 0 }, + { "facility", eCmdHdlrFacility, 0 }, + { "ruleset", eCmdHdlrString, 0 }, + { "readmode", eCmdHdlrInt, 0 }, + { "maxlinesatonce", eCmdHdlrInt, 0 }, + { "maxsubmitatonce", eCmdHdlrInt, 0 }, + { "persiststateinterval", eCmdHdlrInt, 0 } +}; +static struct cnfparamblk inppblk = + { CNFPARAMBLK_VERSION, + sizeof(inppdescr)/sizeof(struct cnfparamdescr), + inppdescr + }; + #include "im-helper.h" /* must be included AFTER the type definitions! */ /* enqueue the read file line as a message. The provided string is @@ -358,7 +377,6 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) inst->pszFileName = (uchar*) strdup((char*) cs.pszFileName); inst->pszTag = (uchar*) strdup((char*) cs.pszFileTag); inst->pszStateFile = (uchar*) strdup((char*) cs.pszStateFile); - inst->nMultiSub = NUM_MULTISUB; inst->iSeverity = cs.iSeverity; inst->iFacility = cs.iFacility; inst->maxLinesAtOnce = cs.maxLinesAtOnce; @@ -413,6 +431,61 @@ finalize_it: RETiRet; } + +BEGINnewInpInst + struct cnfparamvals *pvals; + instanceConf_t *inst; + int i; +CODESTARTnewInpInst + DBGPRINTF("newInpInst (imfile)\n"); + + pvals = nvlstGetParams(lst, &inppblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, + "imfile: required parameter are missing\n"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("input param blk in imfile:\n"); + cnfparamsPrint(&inppblk, pvals); + } + + CHKiRet(createInstance(&inst)); + + for(i = 0 ; i < inppblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(inppblk.descr[i].name, "file")) { + inst->pszFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "statefile")) { + inst->pszStateFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "tag")) { + inst->pszTag = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "ruleset")) { + inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "severity")) { + inst->iSeverity = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "facility")) { + inst->iSeverity = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "readmode")) { + inst->readMode = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "maxlinesatonce")) { + inst->maxLinesAtOnce = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "persistStateInterval")) { + inst->iPersistStateInterval = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "maxsubmitatonce")) { + inst->nMultiSub = pvals[i].val.d.n; + } else { + dbgprintf("imfile: program error, non-handled " + "param '%s'\n", inppblk.descr[i].name); + } + } +finalize_it: +CODE_STD_FINALIZERnewInpInst + cnfparamvalsDestruct(pvals, &inppblk); +ENDnewInpInst + BEGINbeginCnfLoad CODESTARTbeginCnfLoad loadModConf = pModConf; @@ -474,7 +547,6 @@ CODESTARTactivateCnf addListner(inst); } /* if we could not set up any listners, there is no point in running... */ - //if(lcnfRoot == NULL) { if(iFilPtr == 0) { errmsg.LogError(0, NO_ERRCODE, "imfile: no file monitors could be started, " "input not activated.\n"); @@ -488,7 +560,9 @@ BEGINfreeCnf instanceConf_t *inst, *del; CODESTARTfreeCnf for(inst = pModConf->root ; inst != NULL ; ) { - // free(inst->pszBindPort); + free(inst->pszBindRuleset); + free(inst->pszFileName); + free(inst->pszTag); del = inst; inst = inst->next; free(del); @@ -678,6 +752,7 @@ BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES CODEqueryEtryPt_STD_CONF2_QUERIES +CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt -- cgit v1.2.3 From 71664616132a47c2b951d72432031283ba040f79 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 27 Sep 2012 08:54:28 +0200 Subject: imfile: implement support for module parameters via module() stmt --- plugins/imfile/imfile.c | 86 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 9 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 4edd550d..83f94296 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -64,7 +64,11 @@ DEFobjCurrIf(strm) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) -#define NUM_MULTISUB 1024 /* max number of submits -- TODO: make configurable */ +static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */ + +#define NUM_MULTISUB 1024 /* default max number of submits */ +#define DFLT_PollInterval 10 + typedef struct fileInfo_s { uchar *pszFileName; uchar *pszTag; @@ -86,7 +90,7 @@ static struct configSettings_s { uchar *pszFileTag; uchar *pszStateFile; uchar *pszBindRuleset; - int iPollInterval; /* number of seconds to sleep when there was no file activity */ + int iPollInterval; int iPersistStateInterval; /* how often if state file to be persisted? (default 0->never) */ int iFacility; /* local0 */ int iSeverity; /* notice, as of rfc 3164 */ @@ -117,7 +121,8 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a /* config variables */ struct modConfData_s { - rsconf_t *pConf; /* our overall config object */ + rsconf_t *pConf; /* our overall config object */ + int iPollInterval; /* number of seconds to sleep when there was no file activity */ instanceConf_t *root, *tail; sbool configSetViaV2Method; }; @@ -130,6 +135,16 @@ static fileInfo_t files[MAX_INPUT_FILES]; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ +/* module-global parameters */ +static struct cnfparamdescr modpdescr[] = { + { "pollinginterval", eCmdHdlrInt, 0 } +}; +static struct cnfparamblk modpblk = + { CNFPARAMBLK_VERSION, + sizeof(modpdescr)/sizeof(struct cnfparamdescr), + modpdescr + }; + /* input instance parameters */ static struct cnfparamdescr inppdescr[] = { { "file", eCmdHdlrString, CNFPARAM_REQUIRED }, @@ -491,12 +506,14 @@ CODESTARTbeginCnfLoad loadModConf = pModConf; pModConf->pConf = pConf; /* init our settings */ + loadModConf->iPollInterval = DFLT_PollInterval; loadModConf->configSetViaV2Method = 0; + bLegacyCnfModGlobalsPermitted = 1; /* init legacy config vars */ cs.pszFileName = NULL; cs.pszFileTag = NULL; cs.pszStateFile = NULL; - cs.iPollInterval = 10; + cs.iPollInterval = DFLT_PollInterval; cs.iPersistStateInterval = 0; cs.iFacility = 128; cs.iSeverity = 5; @@ -506,13 +523,59 @@ CODESTARTbeginCnfLoad ENDbeginCnfLoad +BEGINsetModCnf + struct cnfparamvals *pvals = NULL; + int i; +CODESTARTsetModCnf + pvals = nvlstGetParams(lst, &modpblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "imfile: error processing module " + "config parameters [module(...)]"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("module (global) param blk for imfile:\n"); + cnfparamsPrint(&modpblk, pvals); + } + + for(i = 0 ; i < modpblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(modpblk.descr[i].name, "pollinginterval")) { + if(pvals[i].val.d.n < 1) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, + "imfile: polling interval cannot be set below 1 - ignored"); + } else { + loadModConf->iPollInterval = (int) pvals[i].val.d.n; + } + } else { + dbgprintf("imfile: program error, non-handled " + "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); + } + } + + /* remove all of our legacy handlers, as they can not used in addition + * the the new-style config method. + */ + bLegacyCnfModGlobalsPermitted = 0; + loadModConf->configSetViaV2Method = 1; + +finalize_it: + if(pvals != NULL) + cnfparamvalsDestruct(pvals, &modpblk); +ENDsetModCnf + + + BEGINendCnfLoad CODESTARTendCnfLoad if(!loadModConf->configSetViaV2Method) { /* persist module-specific settings from legacy config system */ + loadModConf->iPollInterval = cs.iPollInterval; } + dbgprintf("imfile: polling interval is %d\n", loadModConf->iPollInterval); -//finalize_it: loadModConf = NULL; /* done loading */ /* free legacy config vars */ free(cs.pszFileName); @@ -563,6 +626,7 @@ CODESTARTfreeCnf free(inst->pszBindRuleset); free(inst->pszFileName); free(inst->pszTag); + free(inst->pszStateFile); del = inst; inst = inst->next; free(del); @@ -631,7 +695,7 @@ CODESTARTrunInput * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 */ if(glbl.GetGlobalInputTermState() == 0) - srSleep(cs.iPollInterval, 10); + srSleep(runModConf->iPollInterval, 10); } DBGPRINTF("imfile: terminating upon request of rsyslog core\n"); @@ -752,6 +816,7 @@ BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES CODEqueryEtryPt_STD_CONF2_QUERIES +CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt @@ -776,7 +841,7 @@ resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unus cs.pszFileTag = NULL; /* set defaults... */ - cs.iPollInterval = 10; + cs.iPollInterval = DFLT_PollInterval; cs.iFacility = 128; /* local0 */ cs.iSeverity = 5; /* notice, as of rfc 3164 */ cs.readMode = 0; @@ -825,8 +890,6 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &cs.iSeverity, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility, NULL, &cs.iFacility, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, - NULL, &cs.iPollInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilereadmode", 0, eCmdHdlrInt, NULL, &cs.readMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilemaxlinesatonce", 0, eCmdHdlrSize, @@ -838,6 +901,11 @@ CODEmodInit_QueryRegCFSLineHdlr /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, addInstance, NULL, STD_LOADABLE_MODULE_ID)); + /* module-global config params - will be disabled in configs that are loaded + * via module(...). + */ + CHKiRet(regCfSysLineHdlr2((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, + NULL, &cs.iPollInterval, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit -- cgit v1.2.3 From 2ce900aea233b9f8b0447658f2dc3565c3103e78 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 27 Sep 2012 10:03:12 +0200 Subject: bugfix: config errors did not always cause statement to fail This could lead to startup with invalid parameters. --- plugins/imfile/imfile.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 83f94296..462a5e78 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -137,7 +137,7 @@ static prop_t *pInputName = NULL; /* there is only one global inputName for all /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { - { "pollinginterval", eCmdHdlrInt, 0 } + { "pollinginterval", eCmdHdlrPositiveInt, 0 } }; static struct cnfparamblk modpblk = { CNFPARAMBLK_VERSION, @@ -543,12 +543,7 @@ CODESTARTsetModCnf if(!pvals[i].bUsed) continue; if(!strcmp(modpblk.descr[i].name, "pollinginterval")) { - if(pvals[i].val.d.n < 1) { - errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, - "imfile: polling interval cannot be set below 1 - ignored"); - } else { - loadModConf->iPollInterval = (int) pvals[i].val.d.n; - } + loadModConf->iPollInterval = (int) pvals[i].val.d.n; } else { dbgprintf("imfile: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); -- cgit v1.2.3 From f2f85fcf446dcfb8ca9a21dff6a292bf7f68607f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 27 Sep 2012 18:38:53 +0200 Subject: fix whitespace issue --- plugins/imfile/imfile.c | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 462a5e78..453b6b05 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -562,7 +562,6 @@ finalize_it: ENDsetModCnf - BEGINendCnfLoad CODESTARTendCnfLoad if(!loadModConf->configSetViaV2Method) { -- cgit v1.2.3 From 4269e4578118f089021bc15cdd82bb0182a97aaf Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 9 Oct 2012 18:54:25 +0200 Subject: new ratelimit: interface plumbing added no actual implementation yet done --- plugins/imfile/imfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 453b6b05..64a7e032 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -191,7 +191,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetRuleset(pMsg, pInfo->pRuleset); pInfo->multiSub.ppMsgs[pInfo->multiSub.nElem++] = pMsg; if(pInfo->multiSub.nElem == pInfo->multiSub.maxElem) - CHKiRet(multiSubmitMsg(&pInfo->multiSub)); + CHKiRet(multiSubmitMsg2(&pInfo->multiSub, NULL)); finalize_it: RETiRet; } @@ -306,7 +306,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) finalize_it: if(pThis->multiSub.nElem > 0) { /* submit everything that was not yet submitted */ - CHKiRet(multiSubmitMsg(&pThis->multiSub)); + CHKiRet(multiSubmitMsg2(&pThis->multiSub, NULL)); } ; /*EMPTY STATEMENT - needed to keep compiler happy - see below! */ /* Note: the problem above is that pthread:cleanup_pop() is a macro which -- cgit v1.2.3 From 2a6ff7d53d1c30f0d7efd022cf321736870c5629 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 15 Oct 2012 08:55:12 +0200 Subject: interface cleanup (probably not final) --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 64a7e032..d6e6ad0e 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -191,7 +191,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetRuleset(pMsg, pInfo->pRuleset); pInfo->multiSub.ppMsgs[pInfo->multiSub.nElem++] = pMsg; if(pInfo->multiSub.nElem == pInfo->multiSub.maxElem) - CHKiRet(multiSubmitMsg2(&pInfo->multiSub, NULL)); + CHKiRet(multiSubmitMsg(&pInfo->multiSub)); finalize_it: RETiRet; } -- cgit v1.2.3 From 3806643baa9fe0d50fb36080e4ab3a078b8a5952 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 15 Oct 2012 11:19:22 +0200 Subject: ratelimiter: enable thread-safe mode & (related) API changes --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index d6e6ad0e..453b6b05 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -306,7 +306,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) finalize_it: if(pThis->multiSub.nElem > 0) { /* submit everything that was not yet submitted */ - CHKiRet(multiSubmitMsg2(&pThis->multiSub, NULL)); + CHKiRet(multiSubmitMsg(&pThis->multiSub)); } ; /*EMPTY STATEMENT - needed to keep compiler happy - see below! */ /* Note: the problem above is that pthread:cleanup_pop() is a macro which -- cgit v1.2.3 From a3a3a322d8c7d40dfed0765457d26a484a624bce Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 15 Oct 2012 12:22:16 +0200 Subject: imfile: converted to new ratelimit interface --- plugins/imfile/imfile.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 453b6b05..99210b76 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -48,6 +48,7 @@ #include "prop.h" #include "stringbuf.h" #include "ruleset.h" +#include "ratelimit.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ MODULE_TYPE_NOKEEP @@ -82,6 +83,7 @@ typedef struct fileInfo_s { strm_t *pStrm; /* its stream (NULL if not assigned) */ int readMode; /* which mode to use in ReadMulteLine call? */ ruleset_t *pRuleset; /* ruleset to bind listener to (use system default if unspecified) */ + ratelimit_t *ratelimiter; multi_submit_t multiSub; } fileInfo_t; @@ -189,9 +191,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); MsgSetRuleset(pMsg, pInfo->pRuleset); - pInfo->multiSub.ppMsgs[pInfo->multiSub.nElem++] = pMsg; - if(pInfo->multiSub.nElem == pInfo->multiSub.maxElem) - CHKiRet(multiSubmitMsg(&pInfo->multiSub)); + ratelimitAddMsg(pInfo->ratelimiter, &pInfo->multiSub, pMsg); finalize_it: RETiRet; } @@ -304,18 +304,7 @@ static rsRetVal pollFile(fileInfo_t *pThis, int *pbHadFileData) } finalize_it: - if(pThis->multiSub.nElem > 0) { - /* submit everything that was not yet submitted */ - CHKiRet(multiSubmitMsg(&pThis->multiSub)); - } - ; /*EMPTY STATEMENT - needed to keep compiler happy - see below! */ - /* Note: the problem above is that pthread:cleanup_pop() is a macro which - * evaluates to something like "} while(0);". So the code would become - * "finalize_it: }", that is a label without a statement. The C standard does - * not permit this. So we add an empty statement "finalize_it: ; }" and - * everybody is happy. Note that without the ;, an error is reported only - * on some platforms/compiler versions. -- rgerhards, 2008-08-15 - */ + multiSubmitFlush(&pThis->multiSub); pthread_cleanup_pop(0); if(pCStr != NULL) { @@ -423,6 +412,7 @@ addListner(instanceConf_t *inst) pThis->lenTag = ustrlen(pThis->pszTag); pThis->pszStateFile = (uchar*) strdup((char*) inst->pszStateFile); + CHKiRet(ratelimitNew(&pThis->ratelimiter)); CHKmalloc(pThis->multiSub.ppMsgs = MALLOC(inst->nMultiSub * sizeof(msg_t*))); pThis->multiSub.maxElem = inst->nMultiSub; pThis->multiSub.nElem = 0; @@ -773,6 +763,8 @@ CODESTARTafterRun persistStrmState(&files[i]); strm.Destruct(&(files[i].pStrm)); } + ratelimitDestruct(files[i].ratelimiter); + free(files[i].multiSub.ppMsgs); free(files[i].pszFileName); free(files[i].pszTag); free(files[i].pszStateFile); -- cgit v1.2.3 From 34a88a7e9a9501593b6fe9f79cc96963c4da7cde Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 15 Oct 2012 16:39:36 +0200 Subject: ratelimit: added linux-like ratelimiter type --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 99210b76..9a8a0373 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -412,7 +412,7 @@ addListner(instanceConf_t *inst) pThis->lenTag = ustrlen(pThis->pszTag); pThis->pszStateFile = (uchar*) strdup((char*) inst->pszStateFile); - CHKiRet(ratelimitNew(&pThis->ratelimiter)); + CHKiRet(ratelimitNew(&pThis->ratelimiter, "imfile", inst->pszFileName)); CHKmalloc(pThis->multiSub.ppMsgs = MALLOC(inst->nMultiSub * sizeof(msg_t*))); pThis->multiSub.maxElem = inst->nMultiSub; pThis->multiSub.nElem = 0; -- cgit v1.2.3 From 68414e7815813cf7a433b9b8a8cfbb28ec27c637 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 15 Oct 2012 17:19:12 +0200 Subject: cosmetic: remove compiler warning --- plugins/imfile/imfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 9a8a0373..d50f917e 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -412,7 +412,7 @@ addListner(instanceConf_t *inst) pThis->lenTag = ustrlen(pThis->pszTag); pThis->pszStateFile = (uchar*) strdup((char*) inst->pszStateFile); - CHKiRet(ratelimitNew(&pThis->ratelimiter, "imfile", inst->pszFileName)); + CHKiRet(ratelimitNew(&pThis->ratelimiter, "imfile", (char*)inst->pszFileName)); CHKmalloc(pThis->multiSub.ppMsgs = MALLOC(inst->nMultiSub * sizeof(msg_t*))); pThis->multiSub.maxElem = inst->nMultiSub; pThis->multiSub.nElem = 0; -- cgit v1.2.3 From f522a3fc64cf95d36609ad4f0f9b119c3fba06a2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Dec 2012 15:08:30 +0100 Subject: bugfix: very minimal bugfix in imfile not really relevant for production, a few KB were lost during initialization phase if no state file was present --- plugins/imfile/imfile.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index d50f917e..0f155c10 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -246,6 +246,8 @@ finalize_it: strm.Destruct(&psSF); if(iRet != RS_RET_OK) { + if(pThis->pStrm != NULL) + strm.Destruct(&pThis->pStrm); CHKiRet(strm.Construct(&pThis->pStrm)); CHKiRet(strm.SettOperationsMode(pThis->pStrm, STREAMMODE_READ)); CHKiRet(strm.SetsType(pThis->pStrm, STREAMTYPE_FILE_MONITOR)); -- cgit v1.2.3 From 35bafbef04a8f7ba56abebbed337f79b8d6dd67f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 20 Mar 2013 17:05:18 +0100 Subject: imfile: now detects file change when rsyslog was inactive Previosly, this case could not be detected, so if a file was overwritten or rotated away while rsyslog was stopped, some data was missing. This is now detected and the new file being forwarded right from the beginning. closes: http://bugzilla.adiscon.com/show_bug.cgi?id=228 --- plugins/imfile/imfile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 0f155c10..6ce08fd4 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -235,6 +235,7 @@ openFile(fileInfo_t *pThis) /* read back in the object */ CHKiRet(obj.Deserialize(&pThis->pStrm, (uchar*) "strm", psSF, NULL, pThis)); + strm.CheckFileChange(pThis->pStrm); CHKiRet(strm.SeekCurrOffs(pThis->pStrm)); /* note: we do not delete the state file, so that the last position remains -- cgit v1.2.3 From b96674bbc9439f107c700d75e69268ee75e0387e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 20 Mar 2013 18:10:17 +0100 Subject: imfile: errors persisting state file are now reported closes: http://bugzilla.adiscon.com/show_bug.cgi?id=292 --- plugins/imfile/imfile.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'plugins/imfile/imfile.c') diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 6ce08fd4..349acead 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -739,12 +739,20 @@ persistStrmState(fileInfo_t *pInfo) CHKiRet(strm.ConstructFinalize(psSF)); CHKiRet(strm.Serialize(pInfo->pStrm, psSF)); + CHKiRet(strm.Flush(psSF)); CHKiRet(strm.Destruct(&psSF)); finalize_it: if(psSF != NULL) strm.Destruct(&psSF); + + if(iRet != RS_RET_OK) { + errmsg.LogError(0, iRet, "imfile: could not persist state " + "file %s - data may be repeated on next " + "startup. Is WorkDirectory set?", + pInfo->pszStateFile); + } RETiRet; } -- cgit v1.2.3