summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-02-13 07:29:44 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2008-02-13 07:29:44 +0000
commit89a9e10228e18bfc175515c6c389a3780be29095 (patch)
tree700f329d71cc7412810825d5bd89d197cce5b8ba /plugins
parent93367e335719586cf2482eb2876c223509e6ecfc (diff)
downloadrsyslog-89a9e10228e18bfc175515c6c389a3780be29095.tar.gz
rsyslog-89a9e10228e18bfc175515c6c389a3780be29095.tar.xz
rsyslog-89a9e10228e18bfc175515c6c389a3780be29095.zip
cleaned up imfile.c
Diffstat (limited to 'plugins')
-rw-r--r--plugins/imfile/imfile.c302
1 files changed, 19 insertions, 283 deletions
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<yourname>, then replace
- * all references to imtemplate in Makefile.am to im<yourname>. 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<something>. 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
- *
- * $Input<moduleobject>ObjObjName
- *
- * 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: