diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2008-02-01 17:51:07 +0000 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2008-02-01 17:51:07 +0000 |
commit | 9b1c0e2973c7222c163a8678830f1d072ba9c0c6 (patch) | |
tree | c10cac34aa701e6de92033cc533abc247c3a4f8e | |
parent | 812936d199ac47d617153578ef332c202487ef69 (diff) | |
download | rsyslog-9b1c0e2973c7222c163a8678830f1d072ba9c0c6.tar.gz rsyslog-9b1c0e2973c7222c163a8678830f1d072ba9c0c6.tar.xz rsyslog-9b1c0e2973c7222c163a8678830f1d072ba9c0c6.zip |
very quickly hacked a rought outline of the file monitor (without any
guarantees)
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | configure.ac | 22 | ||||
-rw-r--r-- | plugins/imfile/Makefile.am | 6 | ||||
-rw-r--r-- | plugins/imfile/imfile.c | 633 |
4 files changed, 665 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index a5c00de3..bc6360a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -114,3 +114,7 @@ endif if ENABLE_IMTEMPLATE SUBDIRS += plugins/imtemplate endif + +if ENABLE_IMFILE +SUBDIRS += plugins/imfile +endif diff --git a/configure.ac b/configure.ac index c9619bc5..592fea1d 100644 --- a/configure.ac +++ b/configure.ac @@ -411,6 +411,26 @@ AC_SUBST(snmp_libs) # settings for the template input module; copy and modify this code # if you intend to add your own module. Be sure to replace imtemplate # by the actual name of your module. +AC_ARG_ENABLE(imfile, + [AS_HELP_STRING([--enable-imfile],[file input module enabled @<:@default=no@:>@])], + [case "${enableval}" in + yes) enable_imfile="yes" ;; + no) enable_imfile="no" ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-imfile) ;; + esac], + [enable_imfile=no] +) +# +# you may want to do some library checks here - see snmp, mysql, pgsql modules +# for samples +# +AM_CONDITIONAL(ENABLE_IMFILE, test x$enable_imfile = xyes) + +AM_CONDITIONAL(ENABLE_IMTEMPLATE, test x$enable_imtemplate = xyes) +# end of copy template - be sure to serach for imtemplate to find everything! +# settings for the template input module; copy and modify this code +# if you intend to add your own module. Be sure to replace imtemplate +# by the actual name of your module. AC_ARG_ENABLE(imtemplate, [AS_HELP_STRING([--enable-imtemplate],[Compiles imtemplate template module @<:@default=no@:>@])], [case "${enableval}" in @@ -436,6 +456,7 @@ AC_CONFIG_FILES([Makefile \ plugins/immark/Makefile \ plugins/imklog/Makefile \ plugins/imtemplate/Makefile \ + plugins/imfile/Makefile \ plugins/omtesting/Makefile \ plugins/omgssapi/Makefile \ plugins/ommysql/Makefile \ @@ -453,6 +474,7 @@ echo "Zlib compression support enabled: $enable_zlib" echo "MySql support enabled: $enable_mysql" echo "PostgreSQL support enabled: $enable_pgsql" echo "SNMP support enabled: $enable_snmp" +echo "file input module enabled: $enable_imfile" echo "input template module will be compiled: $enable_imtemplate" echo "Large file support enabled: $enable_largefile" echo "Networking support enabled: $enable_inet" diff --git a/plugins/imfile/Makefile.am b/plugins/imfile/Makefile.am new file mode 100644 index 00000000..ea3c8ec3 --- /dev/null +++ b/plugins/imfile/Makefile.am @@ -0,0 +1,6 @@ +pkglib_LTLIBRARIES = imfile.la + +imfile_la_SOURCES = imfile.c +imfile_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(mudflap_cflags) +imfile_la_LDFLAGS = $(mudflap_libs) -module -avoid-version +imfile_la_LIBADD = 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<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 ;) + * + * 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. + * + * 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 <http://www.gnu.org/licenses/>. + * + * 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 <stdlib.h> +#include <assert.h> +#include <string.h> +#include <errno.h> +#include <pthread.h> /* 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 + * + * $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)); + /* 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: + */ |