diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2008-02-13 07:29:44 +0000 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2008-02-13 07:29:44 +0000 |
commit | 89a9e10228e18bfc175515c6c389a3780be29095 (patch) | |
tree | 700f329d71cc7412810825d5bd89d197cce5b8ba /plugins | |
parent | 93367e335719586cf2482eb2876c223509e6ecfc (diff) | |
download | rsyslog-89a9e10228e18bfc175515c6c389a3780be29095.tar.gz rsyslog-89a9e10228e18bfc175515c6c389a3780be29095.tar.bz2 rsyslog-89a9e10228e18bfc175515c6c389a3780be29095.zip |
cleaned up imfile.c
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/imfile/imfile.c | 302 |
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: |