diff options
Diffstat (limited to 'runtime/modules.c')
-rw-r--r-- | runtime/modules.c | 171 |
1 files changed, 132 insertions, 39 deletions
diff --git a/runtime/modules.c b/runtime/modules.c index 4541bddf..69c89790 100644 --- a/runtime/modules.c +++ b/runtime/modules.c @@ -11,7 +11,7 @@ * * File begun on 2007-07-22 by RGerhards * - * Copyright 2007, 2009 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007-2011 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * @@ -55,6 +55,7 @@ #endif #include "cfsysline.h" +#include "rsconf.h" #include "modules.h" #include "errmsg.h" #include "parser.h" @@ -80,9 +81,7 @@ static modInfo_t *pLoadedModulesLast = NULL; /* tail-pointer */ /* already dlopen()-ed libs */ static struct dlhandle_s *pHandles = NULL; -/* config settings */ -uchar *pModDir = NULL; /* read-only after startup */ - +static uchar *pModDir; /* directory where loadable modules are found */ /* we provide a set of dummy functions for modules that do not support the * some interfaces. @@ -319,7 +318,7 @@ static uchar *modGetStateName(modInfo_t *pThis) /* Add a module to the loaded module linked list */ static inline void -addModToList(modInfo_t *pThis) +addModToGlblList(modInfo_t *pThis) { assert(pThis != NULL); @@ -334,6 +333,53 @@ addModToList(modInfo_t *pThis) } +/* Add a module to the config module list for current loadConf + */ +rsRetVal +addModToCnfList(modInfo_t *pThis) +{ + cfgmodules_etry_t *pNew; + cfgmodules_etry_t *pLast; + DEFiRet; + assert(pThis != NULL); + + if(loadConf == NULL) { + /* we are in an early init state */ + FINALIZE; + } + + /* check for duplicates and, as a side-activity, identify last node */ + pLast = loadConf->modules.root; + if(pLast != NULL) { + while(1) { /* loop broken inside */ + if(pLast->pMod == pThis) { + DBGPRINTF("module '%s' already in this config\n", modGetName(pThis)); + FINALIZE; + } + if(pLast->next == NULL) + break; + pLast = pLast -> next; + } + } + + /* if we reach this point, pLast is the tail pointer */ + + CHKmalloc(pNew = MALLOC(sizeof(cfgmodules_etry_t))); + pNew->next = NULL; + pNew->pMod = pThis; + + if(pLast == NULL) { + loadConf->modules.root = pNew; + } else { + /* there already exist entries */ + pLast->next = pNew; + } + +finalize_it: + RETiRet; +} + + /* Get the next module pointer - this is used to traverse the list. * The function returns the next pointer or NULL, if there is no next one. * The last object must be provided to the function. If NULL is provided, @@ -355,19 +401,31 @@ static modInfo_t *GetNxt(modInfo_t *pThis) /* this function is like GetNxt(), but it returns pointers to - * modules of specific type only. As we currently deal just with output modules, - * it is a dummy, to be filled with real code later. - * rgerhards, 2007-07-24 + * modules of specific type only. Only modules from the provided + * config are returned. Note that processing speed could be improved, + * but this is really not relevant, as config file loading is not really + * something we are concerned about in regard to runtime. */ -static modInfo_t *GetNxtType(modInfo_t *pThis, eModType_t rqtdType) +static modInfo_t *GetNxtCnfType(rsconf_t *cnf, modInfo_t *pThis, eModType_t rqtdType) { - modInfo_t *pMod = pThis; + cfgmodules_etry_t *node; + + if(pThis == NULL) { /* start at beginning of module list */ + node = cnf->modules.root; + } else { /* start at last location - then we need to find the module in the config list */ + for(node = cnf->modules.root ; node != NULL && node->pMod != pThis ; node = node->next) + /*search only, all done in for() */; + if(node != NULL) + node = node->next; /* skip to NEXT element in list */ + } - do { - pMod = GetNxt(pMod); - } while(!(pMod == NULL || pMod->eType == rqtdType)); /* warning: do ... while() */ +dbgprintf("XXXX: entering node, ptr %p: %s\n", node, (node == NULL)? "":modGetName(node->pMod)); + while(node != NULL && node->pMod->eType != rqtdType) { + node = node->next; /* warning: do ... while() */ +dbgprintf("XXXX: in loop, ptr %p: %s\n", node, (node == NULL)? "":modGetName(node->pMod)); + } - return pMod; + return (node == NULL) ? NULL : node->pMod; } @@ -409,7 +467,8 @@ finalize_it: * everything needed to fully initialize the module. */ static rsRetVal -doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_t*), uchar *name, void *pModHdlr) +doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_t*), + uchar *name, void *pModHdlr, modInfo_t **pNewModule) { rsRetVal localRet; modInfo_t *pNew = NULL; @@ -470,6 +529,8 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"doAction", &pNew->mod.om.doAction)); CHKiRet((*pNew->modQueryEtryPt)((uchar*)"parseSelectorAct", &pNew->mod.om.parseSelectorAct)); CHKiRet((*pNew->modQueryEtryPt)((uchar*)"tryResume", &pNew->tryResume)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"newScope", &pNew->mod.om.newScope)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"restoreScope", &pNew->mod.om.restoreScope)); /* try load optional interfaces */ localRet = (*pNew->modQueryEtryPt)((uchar*)"doHUP", &pNew->doHUP); if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) @@ -569,12 +630,14 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_ } /* we initialized the structure, now let's add it to the linked list of modules */ - addModToList(pNew); + addModToGlblList(pNew); + *pNewModule = pNew; finalize_it: if(iRet != RS_RET_OK) { if(pNew != NULL) moduleDestruct(pNew); + *pNewModule = NULL; } RETiRet; @@ -623,6 +686,8 @@ static void modPrintList(void) dbgprintf("\tparseSelectorAct: 0x%lx\n", (unsigned long) pMod->mod.om.parseSelectorAct); dbgprintf("\ttryResume: 0x%lx\n", (unsigned long) pMod->tryResume); dbgprintf("\tdoHUP: 0x%lx\n", (unsigned long) pMod->doHUP); + dbgprintf("\tnewScope: 0x%lx\n", (unsigned long) pMod->mod.om.newScope); + dbgprintf("\trestoreScope: 0x%lx\n", (unsigned long) pMod->mod.om.restoreScope); dbgprintf("\tBeginTransaction: 0x%lx\n", (unsigned long) ((pMod->mod.om.beginTransaction == dummyBeginTransaction) ? 0 : pMod->mod.om.beginTransaction)); @@ -751,6 +816,27 @@ modUnloadAndDestructAll(eModLinkType_t modLinkTypesToUnload) RETiRet; } +/* find module with given name in global list */ +static inline rsRetVal +findModule(uchar *pModName, int iModNameLen, modInfo_t **pMod) +{ + modInfo_t *pModInfo; + uchar *pModNameCmp; + DEFiRet; + + pModInfo = GetNxt(NULL); + while(pModInfo != NULL) { + if(!strncmp((char *) pModName, (char *) (pModNameCmp = modGetName(pModInfo)), iModNameLen) && + (!*(pModNameCmp + iModNameLen) || !strcmp((char *) pModNameCmp + iModNameLen, ".so"))) { + dbgprintf("Module '%s' found\n", pModName); + break; + } + pModInfo = GetNxt(pModInfo); + } + *pMod = pModInfo; + RETiRet; +} + /* load a module and initialize it, based on doModLoad() from conf.c * rgerhards, 2008-03-05 @@ -760,15 +846,20 @@ modUnloadAndDestructAll(eModLinkType_t modLinkTypesToUnload) * configuration file processing, which is executed on a single thread. Should we * change that design at any stage (what is unlikely), we need to find a * replacement. + * rgerhards, 2011-04-27: + * Parameter "bConfLoad" tells us if the load was triggered by a config handler, in + * which case we need to tie the loaded module to the current config. If bConfLoad == 0, + * the system loads a module for internal reasons, this is not directly tied to a + * configuration. We could also think if it would be useful to add only certain types + * of modules, but the current implementation at least looks simpler. */ static rsRetVal -Load(uchar *pModName) +Load(uchar *pModName, sbool bConfLoad) { DEFiRet; size_t iPathLen, iModNameLen; uchar szPath[PATH_MAX]; - uchar *pModNameCmp; int bHasExtension; void *pModHdlr, *pModInit; modInfo_t *pModInfo; @@ -788,17 +879,16 @@ Load(uchar *pModName) } else bHasExtension = FALSE; - pModInfo = GetNxt(NULL); - while(pModInfo != NULL) { - if(!strncmp((char *) pModName, (char *) (pModNameCmp = modGetName(pModInfo)), iModNameLen) && - (!*(pModNameCmp + iModNameLen) || !strcmp((char *) pModNameCmp + iModNameLen, ".so"))) { - dbgprintf("Module '%s' already loaded\n", pModName); - ABORT_FINALIZE(RS_RET_OK); - } - pModInfo = GetNxt(pModInfo); + CHKiRet(findModule(pModName, iModNameLen, &pModInfo)); + if(pModInfo != NULL) { + if(bConfLoad) + addModToCnfList(pModInfo); + dbgprintf("Module '%s' already loaded\n", pModName); + FINALIZE; } - pModDirCurr = (uchar *)((pModDir == NULL) ? _PATH_MODDIR : (char *)pModDir); + pModDirCurr = (uchar *)((pModDir == NULL) ? + _PATH_MODDIR : (char *)pModDir); pModDirNext = NULL; pModHdlr = NULL; iLoadCnt = 0; @@ -822,7 +912,8 @@ Load(uchar *pModName) } break; } else if(iPathLen > sizeof(szPath) - 1) { - errmsg.LogError(0, NO_ERRCODE, "could not load module '%s', module path too long\n", pModName); + errmsg.LogError(0, NO_ERRCODE, "could not load module '%s', " + "module path too long\n", pModName); ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_PATHLEN); } @@ -848,17 +939,13 @@ Load(uchar *pModName) /* now see if we have an extension and, if not, append ".so" */ if(!bHasExtension) { - /* we do not have an extension and so need to add ".so" - * TODO: I guess this is highly importable, so we should change the - * algo over time... -- rgerhards, 2008-03-05 - */ - /* ... so now add the extension */ strncat((char *) szPath, ".so", sizeof(szPath) - strlen((char*) szPath) - 1); iPathLen += 3; } if(iPathLen + strlen((char*) pModName) >= sizeof(szPath)) { - errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_PATHLEN, "could not load module '%s', path too long\n", pModName); + errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_PATHLEN, + "could not load module '%s', path too long\n", pModName); ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_PATHLEN); } @@ -884,7 +971,8 @@ Load(uchar *pModName) if(!pModHdlr) { if(iLoadCnt) { - errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_DLOPEN, "could not load module '%s', dlopen: %s\n", szPath, dlerror()); + errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_DLOPEN, + "could not load module '%s', dlopen: %s\n", szPath, dlerror()); } else { errmsg.LogError(0, NO_ERRCODE, "could not load module '%s', ModDir was '%s'\n", szPath, ((pModDir == NULL) ? _PATH_MODDIR : (char *)pModDir)); @@ -892,15 +980,19 @@ Load(uchar *pModName) ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_DLOPEN); } if(!(pModInit = dlsym(pModHdlr, "modInit"))) { - errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_NO_INIT, "could not load module '%s', dlsym: %s\n", szPath, dlerror()); + errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_NO_INIT, + "could not load module '%s', dlsym: %s\n", szPath, dlerror()); dlclose(pModHdlr); ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_NO_INIT); } - if((iRet = doModInit(pModInit, (uchar*) pModName, pModHdlr)) != RS_RET_OK) { - errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_INIT_FAILED, "could not load module '%s', rsyslog error %d\n", szPath, iRet); + if((iRet = doModInit(pModInit, (uchar*) pModName, pModHdlr, &pModInfo)) != RS_RET_OK) { + errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_INIT_FAILED, + "could not load module '%s', rsyslog error %d\n", szPath, iRet); dlclose(pModHdlr); ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_INIT_FAILED); } + if(bConfLoad) + addModToCnfList(pModInfo); finalize_it: pthread_mutex_unlock(&mutLoadUnload); @@ -1010,6 +1102,7 @@ CODESTARTObjClassExit(module) * TODO: add again: pthread_mutex_destroy(&mutLoadUnload); */ + free(pModDir); # ifdef DEBUG modUsrPrintAll(); /* debug aid - TODO: integrate with debug.c, at least the settings! */ # endif @@ -1031,7 +1124,7 @@ CODESTARTobjQueryInterface(module) * of course, also affects the "if" above). */ pIf->GetNxt = GetNxt; - pIf->GetNxtType = GetNxtType; + pIf->GetNxtCnfType = GetNxtCnfType; pIf->GetName = modGetName; pIf->GetStateName = modGetStateName; pIf->PrintList = modPrintList; |