From 6a80d9ee504b57e2b815c91698785d4fcd06f62e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Dec 2007 14:41:09 +0000 Subject: - begun to create input module interface and macros - changed module interface to include function to query type --- module-template.h | 51 +++++++++++++++++++---- modules.c | 102 ++++++++++++++++++++-------------------------- omdiscard.c | 2 + omfile.c | 2 + omfwd.c | 2 + omshell.c | 2 + omusrmsg.c | 2 + plugins/immark/immark.c | 46 ++++++++++++++++++--- plugins/ommysql/ommysql.c | 2 + plugins/ompgsql/ompgsql.c | 2 + syslogd.c | 23 ++++++++--- 11 files changed, 158 insertions(+), 78 deletions(-) diff --git a/module-template.h b/module-template.h index e6b9c8dd..d54f5f83 100644 --- a/module-template.h +++ b/module-template.h @@ -26,6 +26,7 @@ #ifndef MODULE_TEMPLATE_H_INCLUDED #define MODULE_TEMPLATE_H_INCLUDED 1 +#include "modules.h" #include "objomsr.h" /* macro to define standard output-module static data members @@ -33,6 +34,22 @@ #define DEF_OMOD_STATIC_DATA \ static rsRetVal (*omsdRegCFSLineHdlr)(); +/* Macro to define the module type. Each module can only have a single type. If + * a module provides multiple types, several separate modules must be created which + * then should share a single library containing the majority of code. This macro + * must be present in each module. -- rgerhards, 2007-12-14 + */ +#define MODULE_TYPE(x)\ +static rsRetVal modGetType(eModType_t *modType) \ + { \ + *modType = x; \ + return RS_RET_OK;\ + } + +#define MODULE_TYPE_INPUT MODULE_TYPE(eMOD_IN) +#define MODULE_TYPE_OUTPUT MODULE_TYPE(eMOD_OUT) +#define MODULE_TYPE_FILTER MODULE_TYPE(EMOD_FILTER) + /* macro to define a unique module id. This must be able to fit in a void*. The * module id must be unique inside a running rsyslogd application. It is used to * track ownership of several objects. Most importantly, when the module is @@ -311,23 +328,35 @@ static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)())\ return iRet;\ } +/* the following definition is the standard block for queryEtryPt for all types + * of modules. It should be included in any module, and typically is so by calling + * the module-type specific macros. + */ +#define CODEqueryEtryPt_STD_MOD_QUERIES \ + if(!strcmp((char*) name, "dbgPrintInstInfo")) {\ + *pEtryPoint = dbgPrintInstInfo;\ + } else if(!strcmp((char*) name, "freeInstance")) {\ + *pEtryPoint = freeInstance;\ + } else if(!strcmp((char*) name, "modExit")) {\ + *pEtryPoint = modExit;\ + } else if(!strcmp((char*) name, "modGetID")) {\ + *pEtryPoint = modGetID;\ + } else if(!strcmp((char*) name, "getType")) {\ + *pEtryPoint = modGetType;\ + } + /* the following definition is the standard block for queryEtryPt for output * modules. This can be used if no specific handling (e.g. to cover version * differences) is needed. */ #define CODEqueryEtryPt_STD_OMOD_QUERIES \ - if(!strcmp((char*) name, "doAction")) {\ + CODEqueryEtryPt_STD_MOD_QUERIES \ + else if(!strcmp((char*) name, "doAction")) {\ *pEtryPoint = doAction;\ } else if(!strcmp((char*) name, "parseSelectorAct")) {\ *pEtryPoint = parseSelectorAct;\ } else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\ *pEtryPoint = isCompatibleWithFeature;\ - } else if(!strcmp((char*) name, "dbgPrintInstInfo")) {\ - *pEtryPoint = dbgPrintInstInfo;\ - } else if(!strcmp((char*) name, "freeInstance")) {\ - *pEtryPoint = freeInstance;\ - } else if(!strcmp((char*) name, "modExit")) {\ - *pEtryPoint = modExit;\ } else if(!strcmp((char*) name, "getWriteFDForSelect")) {\ *pEtryPoint = getWriteFDForSelect;\ } else if(!strcmp((char*) name, "onSelectReadyWrite")) {\ @@ -336,10 +365,14 @@ static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)())\ *pEtryPoint = needUDPSocket;\ } else if(!strcmp((char*) name, "tryResume")) {\ *pEtryPoint = tryResume;\ - } else if(!strcmp((char*) name, "modGetID")) {\ - *pEtryPoint = modGetID;\ } +/* the following definition is the standard block for queryEtryPt for INPUT + * modules. This can be used if no specific handling (e.g. to cover version + * differences) is needed. + */ +#define CODEqueryEtryPt_STD_IMOD_QUERIES \ + CODEqueryEtryPt_STD_MOD_QUERIES /* modInit() * This has an extra parameter, which is the specific name of the modInit diff --git a/modules.c b/modules.c index 87ca7a40..b7ca71eb 100644 --- a/modules.c +++ b/modules.c @@ -208,7 +208,8 @@ finalize_it: rsRetVal doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)()), uchar *name, void *pModHdlr) { DEFiRet; - modInfo_t *pNew; + modInfo_t *pNew = NULL; + rsRetVal (*modGetType)(eModType_t *pType); assert(modInit != NULL); @@ -218,72 +219,52 @@ rsRetVal doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)()) bCfsyslineInitialized = 1; } - if((iRet = moduleConstruct(&pNew)) != RS_RET_OK) - return iRet; - - if((iRet = (*modInit)(1, &pNew->iIFVers, &pNew->modQueryEtryPt, queryHostEtryPt)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; + if((iRet = moduleConstruct(&pNew)) != RS_RET_OK) { + pNew = NULL; + ABORT_FINALIZE(iRet); } + CHKiRet((*modInit)(1, &pNew->iIFVers, &pNew->modQueryEtryPt, queryHostEtryPt)); + if(pNew->iIFVers != 1) { - moduleDestruct(pNew); - return RS_RET_MISSING_INTERFACE; + ABORT_FINALIZE(RS_RET_MISSING_INTERFACE); } + /* We now poll the module to see what type it is. We do this only once as this + * can never change in the lifetime of an module. -- rgerhards, 2007-12-14 + */ + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"getType", &modGetType)); + CHKiRet((iRet = (*modGetType)(&pNew->eType)) != RS_RET_OK); + dbgprintf("module of type %d being loaded.\n", pNew->eType); + /* OK, we know we can successfully work with the module. So we now fill the - * rest of the data elements. + * rest of the data elements. First we load the interfaces common to all + * module types. */ - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"doAction", &pNew->mod.om.doAction)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"parseSelectorAct", &pNew->mod.om.parseSelectorAct)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"isCompatibleWithFeature", - &pNew->isCompatibleWithFeature)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"dbgPrintInstInfo", - &pNew->dbgPrintInstInfo)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"getWriteFDForSelect", &pNew->getWriteFDForSelect)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"onSelectReadyWrite", &pNew->onSelectReadyWrite)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"needUDPSocket", &pNew->needUDPSocket)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"tryResume", &pNew->tryResume)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"freeInstance", &pNew->freeInstance)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"modGetID", &pNew->modGetID)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; - } - if((iRet = (*pNew->modQueryEtryPt)((uchar*)"modExit", &pNew->modExit)) != RS_RET_OK) { - moduleDestruct(pNew); - return iRet; + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"dbgPrintInstInfo", &pNew->dbgPrintInstInfo)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"modGetID", &pNew->modGetID)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"modExit", &pNew->modExit)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeInstance", &pNew->freeInstance)); + + /* ... and now the module-specific interfaces */ + switch(pNew->eType) { + case eMOD_IN: + break; + case eMOD_OUT: + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"doAction", &pNew->mod.om.doAction)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"parseSelectorAct", &pNew->mod.om.parseSelectorAct)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"isCompatibleWithFeature", &pNew->isCompatibleWithFeature)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"getWriteFDForSelect", &pNew->getWriteFDForSelect)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"onSelectReadyWrite", &pNew->onSelectReadyWrite)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"needUDPSocket", &pNew->needUDPSocket)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"tryResume", &pNew->tryResume)); + break; + case eMOD_FILTER: + break; } pNew->pszName = (uchar*) strdup((char*)name); /* we do not care if strdup() fails, we can accept that */ pNew->pModHdlr = pModHdlr; - pNew->eType = eMOD_OUT; /* TODO: take this from module */ /* TODO: take this from module */ if(pModHdlr == NULL) pNew->eLinkType = eMOD_LINK_STATIC; @@ -294,6 +275,12 @@ rsRetVal doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)()) addModToList(pNew); finalize_it: + + if(iRet != RS_RET_OK) { + if(pNew != NULL) + moduleDestruct(pNew); + } + return iRet; } @@ -381,6 +368,5 @@ rsRetVal modUnloadAndDestructDynamic(void) return iRet; } -/* - * vi:set ai: +/* vi:set ai: */ diff --git a/omdiscard.c b/omdiscard.c index 54a63bcd..bfdcdb14 100644 --- a/omdiscard.c +++ b/omdiscard.c @@ -37,6 +37,8 @@ #include "omdiscard.h" #include "module-template.h" +MODULE_TYPE_OUTPUT + /* internal structures */ DEF_OMOD_STATIC_DATA diff --git a/omfile.c b/omfile.c index 46b6c560..7a931606 100644 --- a/omfile.c +++ b/omfile.c @@ -53,6 +53,8 @@ #include "cfsysline.h" #include "module-template.h" +MODULE_TYPE_OUTPUT + /* internal structures */ DEF_OMOD_STATIC_DATA diff --git a/omfwd.c b/omfwd.c index 0d319189..0aa5ed64 100644 --- a/omfwd.c +++ b/omfwd.c @@ -66,6 +66,8 @@ #include "gss-misc.h" #endif +MODULE_TYPE_OUTPUT + #ifdef SYSLOG_INET #define INET_SUSPEND_TIME 60 /* equal to 1 minute * rgerhards, 2005-07-26: This was 3 minutes. As the diff --git a/omshell.c b/omshell.c index cfd0e359..4ada6a94 100644 --- a/omshell.c +++ b/omshell.c @@ -44,6 +44,8 @@ #include "omshell.h" #include "module-template.h" +MODULE_TYPE_OUTPUT + /* internal structures */ DEF_OMOD_STATIC_DATA diff --git a/omusrmsg.c b/omusrmsg.c index c35fd9d6..9b23d9df 100644 --- a/omusrmsg.c +++ b/omusrmsg.c @@ -59,6 +59,8 @@ #include "omusrmsg.h" #include "module-template.h" +MODULE_TYPE_OUTPUT + /* internal structures */ DEF_OMOD_STATIC_DATA diff --git a/plugins/immark/immark.c b/plugins/immark/immark.c index 0236a38c..d70069c5 100644 --- a/plugins/immark/immark.c +++ b/plugins/immark/immark.c @@ -1,4 +1,4 @@ -/* omfwd.c +/* immark.c * This is the implementation of the build-in mark message input module. * * NOTE: read comments in module-template.h to understand how this file @@ -30,13 +30,21 @@ * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" -#if 0 /* IMMARK */ +#if 1 /* IMMARK */ #include #include +#include #include +#include #include #include "rsyslog.h" #include "syslogd.h" +#include "module-template.h" + +MODULE_TYPE_INPUT + +typedef struct _instanceData { +} instanceData; /* This function is called to gather input. It must terminate only * a) on failure (iRet set accordingly) @@ -58,15 +66,15 @@ immark_runInput(void) sigfillset(&sigSet); pthread_sigmask(SIG_BLOCK, &sigSet, NULL); sigemptyset(&sigSet); - sigaddset(&sigSet, SIGTERM); - sigaddset(&sigSet, SIGHUP); + sigaddset(&sigSet, SIGUSR2); pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL); -dbgprintf("immark_runInput running!\n"); while(!bFinished) { dbgprintf("immark pre select\n"); - tvSelectTimeout.tv_sec = 500; + tvSelectTimeout.tv_sec = 5; tvSelectTimeout.tv_usec = 0; select(0, NULL, NULL, NULL, &tvSelectTimeout); + if(bFinished) + break; dbgprintf("immark post select, doing mark, bFinished: %d\n", bFinished); logmsgInternal(LOG_INFO, "-- MARK --", ADDDATE); //logmsgInternal(LOG_INFO, "-- MARK --", ADDDATE|MARK); @@ -74,6 +82,32 @@ dbgprintf("immark post select, doing mark, bFinished: %d\n", bFinished); fprintf(stderr, "immark: finished!\n"); return RS_RET_OK; } + +BEGINfreeInstance +CODESTARTfreeInstance +ENDfreeInstance + + +BEGINdbgPrintInstInfo +CODESTARTdbgPrintInstInfo +ENDdbgPrintInstInfo + + +BEGINmodExit +CODESTARTmodExit +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_IMOD_QUERIES +ENDqueryEtryPt + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = 1; /* so far, we only support the initial definition */ +ENDmodInit #endif /* #if 0 */ /* * vi:set ai: diff --git a/plugins/ommysql/ommysql.c b/plugins/ommysql/ommysql.c index e8e53e76..d67d92eb 100644 --- a/plugins/ommysql/ommysql.c +++ b/plugins/ommysql/ommysql.c @@ -44,6 +44,8 @@ #include "ommysql.h" #include "module-template.h" +MODULE_TYPE_OUTPUT + /* internal structures */ DEF_OMOD_STATIC_DATA diff --git a/plugins/ompgsql/ompgsql.c b/plugins/ompgsql/ompgsql.c index 94f22510..45e3c674 100644 --- a/plugins/ompgsql/ompgsql.c +++ b/plugins/ompgsql/ompgsql.c @@ -43,6 +43,8 @@ #include "ompgsql.h" #include "module-template.h" +MODULE_TYPE_OUTPUT + /* internal structures */ DEF_OMOD_STATIC_DATA diff --git a/syslogd.c b/syslogd.c index f8db3e34..1a09ed3b 100644 --- a/syslogd.c +++ b/syslogd.c @@ -3835,8 +3835,13 @@ static rsRetVal doModLoad(uchar **pp, __attribute__((unused)) void* pVal) dlclose(pModHdlr); ABORT_FINALIZE(RS_RET_ERR); } - if((iRet = doModInit(pModInit, (uchar*) pModName, pModHdlr)) != RS_RET_OK) - return iRet; + if((iRet = doModInit(pModInit, (uchar*) pModName, pModHdlr)) != RS_RET_OK) { + snprintf((char *) errMsg, sizeof(errMsg), "could not load module '%s', rsyslog error %d\n", szPath, iRet); + errMsg[sizeof(errMsg)/sizeof(uchar) - 1] = '\0'; + logerror((char *) errMsg); + dlclose(pModHdlr); + ABORT_FINALIZE(RS_RET_ERR); + } skipWhiteSpace(pp); /* skip over any whitespace */ @@ -6074,11 +6079,12 @@ static void mainThread() */ mainloop(); - - /* do any de-init's that need to be done AFTER this comment */ - die(bFinished); } +static void sigusr2Dummy(int sig) +{ +dbgprintf("sigusr2Dummy called!\n"); +} /* This is the main entry point into rsyslogd. Over time, we should try to * modularize it a bit more... @@ -6351,6 +6357,8 @@ int main(int argc, char **argv) sigaction(SIGALRM, &sigAct, NULL); sigAct.sa_handler = Debug ? debug_switch : SIG_IGN; sigaction(SIGUSR1, &sigAct, NULL); + sigAct.sa_handler = sigusr2Dummy; + sigaction(SIGUSR2, &sigAct, NULL); sigAct.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sigAct, NULL); sigaction(SIGXFSZ, &sigAct, NULL); /* do not abort if 2gig file limit is hit */ @@ -6385,12 +6393,17 @@ int main(int argc, char **argv) * do a blocking wait on it - it makese sense... ;) rgerhards, 2007-10-08 */ #endif + + /* do any de-init's that need to be done AFTER this comment */ #if IMMARK dbgprintf("waiting to join thrdMain\n"); + pthread_kill(thrdMain, SIGUSR2); pthread_join(thrdMain, NULL); dbgprintf("joined thrdMain\n"); #endif +dbgprintf("reaching die\n"); + die(bFinished); return 0; } -- cgit