summaryrefslogtreecommitdiffstats
path: root/modules.c
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-04-16 10:26:54 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-04-16 10:26:54 +0200
commit8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc (patch)
tree8bd92ca19ae3cccd5b160c717960db88bb095e73 /modules.c
parent3af28bbd2dc4c79b242aad3b9e3f45cffe0f19d0 (diff)
downloadrsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.tar.gz
rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.tar.xz
rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.zip
moved files to the runtime
there are still some files left which could go into the runtime, but I think we will delete most of them once we are done with the full modularization.
Diffstat (limited to 'modules.c')
-rw-r--r--modules.c802
1 files changed, 0 insertions, 802 deletions
diff --git a/modules.c b/modules.c
deleted file mode 100644
index 32a71c0c..00000000
--- a/modules.c
+++ /dev/null
@@ -1,802 +0,0 @@
-/* modules.c
- * This is the implementation of syslogd modules object.
- * This object handles plug-ins and build-in modules of all kind.
- *
- * Modules are reference-counted. Anyone who access a module must call
- * Use() before any function is accessed and Release() when he is done.
- * When the reference count reaches 0, rsyslog unloads the module (that
- * may be changed in the future to cache modules). Rsyslog does NOT
- * unload modules with a reference count > 0, even if the unload
- * method is called!
- *
- * File begun on 2007-07-22 by RGerhards
- *
- * Copyright 2007 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"
-#include "rsyslog.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <assert.h>
-#include <errno.h>
-#ifdef OS_BSD
-# include "libgen.h"
-#endif
-
-#include <dlfcn.h> /* TODO: replace this with the libtools equivalent! */
-
-#include <unistd.h>
-#include <sys/file.h>
-
-#include "syslogd.h"
-#include "cfsysline.h"
-#include "modules.h"
-#include "errmsg.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(errmsg)
-
-static modInfo_t *pLoadedModules = NULL; /* list of currently-loaded modules */
-static modInfo_t *pLoadedModulesLast = NULL; /* tail-pointer */
-
-/* config settings */
-uchar *pModDir = NULL; /* read-only after startup */
-
-
-#ifdef DEBUG
-/* we add some home-grown support to track our users (and detect who does not free us). In
- * the long term, this should probably be migrated into debug.c (TODO). -- rgerhards, 2008-03-11
- */
-
-/* add a user to the current list of users (always at the root) */
-static void
-modUsrAdd(modInfo_t *pThis, char *pszUsr)
-{
- modUsr_t *pUsr;
-
- BEGINfunc
- if((pUsr = calloc(1, sizeof(modUsr_t))) == NULL)
- goto finalize_it;
-
- if((pUsr->pszFile = strdup(pszUsr)) == NULL) {
- free(pUsr);
- goto finalize_it;
- }
-
- if(pThis->pModUsrRoot != NULL) {
- pUsr->pNext = pThis->pModUsrRoot;
- }
- pThis->pModUsrRoot = pUsr;
-
-finalize_it:
- ENDfunc;
-}
-
-
-/* remove a user from the current user list
- * rgerhards, 2008-03-11
- */
-static void
-modUsrDel(modInfo_t *pThis, char *pszUsr)
-{
- modUsr_t *pUsr;
- modUsr_t *pPrev = NULL;
-
- for(pUsr = pThis->pModUsrRoot ; pUsr != NULL ; pUsr = pUsr->pNext) {
- if(!strcmp(pUsr->pszFile, pszUsr))
- break;
- else
- pPrev = pUsr;
- }
-
- if(pUsr == NULL) {
- dbgprintf("oops - tried to delete user %s from module %s and it wasn't registered as one...\n",
- pszUsr, pThis->pszName);
- } else {
- if(pPrev == NULL) {
- /* This was at the root! */
- pThis->pModUsrRoot = pUsr->pNext;
- } else {
- pPrev->pNext = pUsr->pNext;
- }
- /* free ressources */
- free(pUsr->pszFile);
- free(pUsr);
- pUsr = NULL; /* just to make sure... */
- }
-}
-
-
-/* print a short list all all source files using the module in question
- * rgerhards, 2008-03-11
- */
-static void
-modUsrPrint(modInfo_t *pThis)
-{
- modUsr_t *pUsr;
-
- for(pUsr = pThis->pModUsrRoot ; pUsr != NULL ; pUsr = pUsr->pNext) {
- dbgprintf("\tmodule %s is currently in use by file %s\n",
- pThis->pszName, pUsr->pszFile);
- }
-}
-
-
-/* print all loaded modules and who is accessing them. This is primarily intended
- * to be called at end of run to detect "module leaks" and who is causing them.
- * rgerhards, 2008-03-11
- */
-//static void
-void
-modUsrPrintAll(void)
-{
- modInfo_t *pMod;
-
- BEGINfunc
- for(pMod = pLoadedModules ; pMod != NULL ; pMod = pMod->pNext) {
- dbgprintf("printing users of loadable module %s, refcount %u, ptr %p, type %d\n", pMod->pszName, pMod->uRefCnt, pMod, pMod->eType);
- modUsrPrint(pMod);
- }
- ENDfunc
-}
-
-#endif /* #ifdef DEBUG */
-
-
-/* Construct a new module object
- */
-static rsRetVal moduleConstruct(modInfo_t **pThis)
-{
- modInfo_t *pNew;
-
- if((pNew = calloc(1, sizeof(modInfo_t))) == NULL)
- return RS_RET_OUT_OF_MEMORY;
-
- /* OK, we got the element, now initialize members that should
- * not be zero-filled.
- */
-
- *pThis = pNew;
- return RS_RET_OK;
-}
-
-
-/* Destructs a module object. The object must not be linked to the
- * linked list of modules. Please note that all other dependencies on this
- * modules must have been removed before (e.g. CfSysLineHandlers!)
- */
-static void moduleDestruct(modInfo_t *pThis)
-{
- assert(pThis != NULL);
- if(pThis->pszName != NULL)
- free(pThis->pszName);
- if(pThis->pModHdlr != NULL) {
-# ifdef VALGRIND
-# warning "dlclose disabled for valgrind"
-# else
- dlclose(pThis->pModHdlr);
-# endif
- }
-
- free(pThis);
-}
-
-
-/* The following function is the queryEntryPoint for host-based entry points.
- * Modules may call it to get access to core interface functions. Please note
- * that utility functions can be accessed via shared libraries - at least this
- * is my current shool of thinking.
- * Please note that the implementation as a query interface allows to take
- * care of plug-in interface version differences. -- rgerhards, 2007-07-31
- */
-static rsRetVal queryHostEtryPt(uchar *name, rsRetVal (**pEtryPoint)())
-{
- DEFiRet;
-
- if((name == NULL) || (pEtryPoint == NULL))
- return RS_RET_PARAM_ERROR;
-
- if(!strcmp((char*) name, "regCfSysLineHdlr")) {
- *pEtryPoint = regCfSysLineHdlr;
- } else if(!strcmp((char*) name, "objGetObjInterface")) {
- *pEtryPoint = objGetObjInterface;
- } else {
- *pEtryPoint = NULL; /* to be on the safe side */
- ABORT_FINALIZE(RS_RET_ENTRY_POINT_NOT_FOUND);
- }
-
-finalize_it:
- RETiRet;
-}
-
-
-/* get the name of a module
- */
-static uchar *modGetName(modInfo_t *pThis)
-{
- return((pThis->pszName == NULL) ? (uchar*) "" : pThis->pszName);
-}
-
-
-/* get the state-name of a module. The state name is its name
- * together with a short description of the module state (which
- * is pulled from the module itself.
- * rgerhards, 2007-07-24
- * TODO: the actual state name is not yet pulled
- */
-static uchar *modGetStateName(modInfo_t *pThis)
-{
- return(modGetName(pThis));
-}
-
-
-/* Add a module to the loaded module linked list
- */
-static inline void
-addModToList(modInfo_t *pThis)
-{
- assert(pThis != NULL);
-
- if(pLoadedModules == NULL) {
- pLoadedModules = pLoadedModulesLast = pThis;
- } else {
- /* there already exist entries */
- pThis->pPrev = pLoadedModulesLast;
- pLoadedModulesLast->pNext = pThis;
- pLoadedModulesLast = pThis;
- }
-}
-
-
-/* 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,
- * it starts at the root of the list. Even in this case, NULL may be
- * returned - then, the list is empty.
- * rgerhards, 2007-07-23
- */
-static modInfo_t *GetNxt(modInfo_t *pThis)
-{
- modInfo_t *pNew;
-
- if(pThis == NULL)
- pNew = pLoadedModules;
- else
- pNew = pThis->pNext;
-
- return(pNew);
-}
-
-
-/* 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
- */
-static modInfo_t *GetNxtType(modInfo_t *pThis, eModType_t rqtdType)
-{
- modInfo_t *pMod = pThis;
-
- do {
- pMod = GetNxt(pMod);
- } while(!(pMod == NULL || pMod->eType == rqtdType)); /* warning: do ... while() */
-
- return pMod;
-}
-
-
-/* Prepare a module for unloading.
- * This is currently a dummy, to be filled when we have a plug-in
- * interface - rgerhards, 2007-08-09
- * rgerhards, 2007-11-21:
- * When this function is called, all instance-data must already have
- * been destroyed. In the case of output modules, this happens when the
- * rule set is being destroyed. When we implement other module types, we
- * need to think how we handle it there (and if we have any instance data).
- * rgerhards, 2008-03-10: reject unload request if the module has a reference
- * count > 0.
- */
-static rsRetVal
-modPrepareUnload(modInfo_t *pThis)
-{
- DEFiRet;
- void *pModCookie;
-
- assert(pThis != NULL);
-
- if(pThis->uRefCnt > 0) {
- dbgprintf("rejecting unload of module '%s' because it has a refcount of %d\n",
- pThis->pszName, pThis->uRefCnt);
- ABORT_FINALIZE(RS_RET_MODULE_STILL_REFERENCED);
- }
-
- CHKiRet(pThis->modGetID(&pModCookie));
- pThis->modExit(); /* tell the module to get ready for unload */
- CHKiRet(unregCfSysLineHdlrs4Owner(pModCookie));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* Add an already-loaded module to the module linked list. This function does
- * everything needed to fully initialize the module.
- */
-static rsRetVal
-doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_t*), uchar *name, void *pModHdlr)
-{
- DEFiRet;
- modInfo_t *pNew = NULL;
- rsRetVal (*modGetType)(eModType_t *pType);
-
- assert(modInit != NULL);
-
- if((iRet = moduleConstruct(&pNew)) != RS_RET_OK) {
- pNew = NULL;
- ABORT_FINALIZE(iRet);
- }
-
- CHKiRet((*modInit)(CURR_MOD_IF_VERSION, &pNew->iIFVers, &pNew->modQueryEtryPt, queryHostEtryPt, pNew));
-
- if(pNew->iIFVers != CURR_MOD_IF_VERSION) {
- 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. First we load the interfaces common to all
- * module types.
- */
- CHKiRet((*pNew->modQueryEtryPt)((uchar*)"modGetID", &pNew->modGetID));
- CHKiRet((*pNew->modQueryEtryPt)((uchar*)"modExit", &pNew->modExit));
-
- /* ... and now the module-specific interfaces */
- switch(pNew->eType) {
- case eMOD_IN:
- CHKiRet((*pNew->modQueryEtryPt)((uchar*)"runInput", &pNew->mod.im.runInput));
- CHKiRet((*pNew->modQueryEtryPt)((uchar*)"willRun", &pNew->mod.im.willRun));
- CHKiRet((*pNew->modQueryEtryPt)((uchar*)"afterRun", &pNew->mod.im.afterRun));
- break;
- case eMOD_OUT:
- CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeInstance", &pNew->freeInstance));
- CHKiRet((*pNew->modQueryEtryPt)((uchar*)"dbgPrintInstInfo", &pNew->dbgPrintInstInfo));
- 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*)"tryResume", &pNew->tryResume));
- break;
- case eMOD_LIB:
- break;
- }
-
- pNew->pszName = (uchar*) strdup((char*)name); /* we do not care if strdup() fails, we can accept that */
- pNew->pModHdlr = pModHdlr;
- /* TODO: take this from module */
- if(pModHdlr == NULL)
- pNew->eLinkType = eMOD_LINK_STATIC;
- else
- pNew->eLinkType = eMOD_LINK_DYNAMIC_LOADED;
-
- /* we initialized the structure, now let's add it to the linked list of modules */
- addModToList(pNew);
-
-finalize_it:
- if(iRet != RS_RET_OK) {
- if(pNew != NULL)
- moduleDestruct(pNew);
- }
-
- RETiRet;
-}
-
-/* Print loaded modules. This is more or less a
- * debug or test aid, but anyhow I think it's worth it...
- * This only works if the dbgprintf() subsystem is initialized.
- * TODO: update for new input modules!
- */
-static void modPrintList(void)
-{
- modInfo_t *pMod;
-
- pMod = GetNxt(NULL);
- while(pMod != NULL) {
- dbgprintf("Loaded Module: Name='%s', IFVersion=%d, ",
- (char*) modGetName(pMod), pMod->iIFVers);
- dbgprintf("type=");
- switch(pMod->eType) {
- case eMOD_OUT:
- dbgprintf("output");
- break;
- case eMOD_IN:
- dbgprintf("input");
- break;
- case eMOD_LIB:
- dbgprintf("library");
- break;
- }
- dbgprintf(" module.\n");
- dbgprintf("Entry points:\n");
- dbgprintf("\tqueryEtryPt: 0x%lx\n", (unsigned long) pMod->modQueryEtryPt);
- dbgprintf("\tdoAction: 0x%lx\n", (unsigned long) pMod->mod.om.doAction);
- dbgprintf("\tparseSelectorAct: 0x%lx\n", (unsigned long) pMod->mod.om.parseSelectorAct);
- dbgprintf("\tdbgPrintInstInfo: 0x%lx\n", (unsigned long) pMod->dbgPrintInstInfo);
- dbgprintf("\tfreeInstance: 0x%lx\n", (unsigned long) pMod->freeInstance);
- dbgprintf("\n");
- pMod = GetNxt(pMod); /* done, go next */
- }
-}
-
-
-/* unlink and destroy a module. The caller must provide a pointer to the module
- * itself as well as one to its immediate predecessor.
- * rgerhards, 2008-02-26
- */
-static rsRetVal
-modUnlinkAndDestroy(modInfo_t **ppThis)
-{
- DEFiRet;
- modInfo_t *pThis;
-
- assert(ppThis != NULL);
- pThis = *ppThis;
- assert(pThis != NULL);
-
- /* first check if we are permitted to unload */
- if(pThis->eType == eMOD_LIB) {
- if(pThis->uRefCnt > 0) {
- dbgprintf("module %s NOT unloaded because it still has a refcount of %u\n",
- pThis->pszName, pThis->uRefCnt);
-# ifdef DEBUG
- //modUsrPrintAll();
-# endif
- ABORT_FINALIZE(RS_RET_MODULE_STILL_REFERENCED);
- }
- }
-
- /* we need to unlink the module before we can destruct it -- rgerhards, 2008-02-26 */
- if(pThis->pPrev == NULL) {
- /* module is root, so we need to set a new root */
- pLoadedModules = pThis->pNext;
- } else {
- pThis->pPrev->pNext = pThis->pNext;
- }
-
- if(pThis->pNext == NULL) {
- pLoadedModulesLast = pThis->pPrev;
- } else {
- pThis->pNext->pPrev = pThis->pPrev;
- }
-
- /* finally, we are ready for the module to go away... */
- dbgprintf("Unloading module %s\n", modGetName(pThis));
- CHKiRet(modPrepareUnload(pThis));
- *ppThis = pThis->pNext;
-
- moduleDestruct(pThis);
-
-finalize_it:
- RETiRet;
-}
-
-
-/* unload all loaded modules of a specific type (use eMOD_ALL if you want to
- * unload all module types). The unload happens only if the module is no longer
- * referenced. So some modules may survive this call.
- * rgerhards, 2008-03-11
- */
-static rsRetVal
-modUnloadAndDestructAll(eModLinkType_t modLinkTypesToUnload)
-{
- DEFiRet;
- modInfo_t *pModCurr; /* module currently being processed */
-
- pModCurr = GetNxt(NULL);
- while(pModCurr != NULL) {
- if(modLinkTypesToUnload == eMOD_LINK_ALL || pModCurr->eLinkType == modLinkTypesToUnload) {
- if(modUnlinkAndDestroy(&pModCurr) == RS_RET_MODULE_STILL_REFERENCED) {
- pModCurr = GetNxt(pModCurr);
- }
- /* Note: if the module was successfully unloaded, it has updated the
- * pModCurr pointer to the next module. So we do NOT need to advance
- * to the next module on successful unload.
- */
- } else {
- pModCurr = GetNxt(pModCurr);
- }
- }
-
-# ifdef DEBUG
- if(pLoadedModules != NULL) {
- dbgprintf("modules still loaded after module.UnloadAndDestructAll:\n");
- modUsrPrintAll();
- }
-# endif
-
- RETiRet;
-}
-
-
-/* load a module and initialize it, based on doModLoad() from conf.c
- * rgerhards, 2008-03-05
- * varmojfekoj added support for dynamically loadable modules on 2007-08-13
- * rgerhards, 2007-09-25: please note that the non-threadsafe function dlerror() is
- * called below. This is ok because modules are currently only loaded during
- * 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.
- */
-static rsRetVal
-Load(uchar *pModName)
-{
- DEFiRet;
-
- size_t iPathLen, iModNameLen;
- uchar szPath[PATH_MAX];
- uchar *pModNameCmp;
- int bHasExtension;
- void *pModHdlr, *pModInit;
- modInfo_t *pModInfo;
-
- assert(pModName != NULL);
- dbgprintf("Requested to load module '%s'\n", pModName);
-
- iModNameLen = strlen((char *) pModName);
- if(iModNameLen > 3 && !strcmp((char *) pModName + iModNameLen - 3, ".so")) {
- iModNameLen -= 3;
- bHasExtension = TRUE;
- } 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);
- }
-
- /* now build our load module name */
- if(*pModName == '/') {
- *szPath = '\0'; /* we do not need to append the path - its already in the module name */
- iPathLen = 0;
- } else {
- *szPath = '\0';
- strncat((char *) szPath, (pModDir == NULL) ? _PATH_MODDIR : (char*) pModDir, sizeof(szPath) - 1);
- iPathLen = strlen((char*) szPath);
- if((szPath[iPathLen - 1] != '/')) {
- if((iPathLen <= sizeof(szPath) - 2)) {
- szPath[iPathLen++] = '/';
- szPath[iPathLen] = '\0';
- } else {
- errmsg.LogError(NO_ERRCODE, "could not load module '%s', path too long\n", pModName);
- ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_PATHLEN);
- }
- }
- }
-
- /* ... add actual name ... */
- strncat((char *) szPath, (char *) pModName, sizeof(szPath) - iPathLen - 1);
-
- /* 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(NO_ERRCODE, "could not load module '%s', path too long\n", pModName);
- ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_PATHLEN);
- }
-
- /* complete load path constructed, so ... GO! */
- dbgprintf("loading module '%s'\n", szPath);
- if(!(pModHdlr = dlopen((char *) szPath, RTLD_NOW))) {
- errmsg.LogError(NO_ERRCODE, "could not load module '%s', dlopen: %s\n", szPath, dlerror());
- ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_DLOPEN);
- }
- if(!(pModInit = dlsym(pModHdlr, "modInit"))) {
- errmsg.LogError(NO_ERRCODE, "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(NO_ERRCODE, "could not load module '%s', rsyslog error %d\n", szPath, iRet);
- dlclose(pModHdlr);
- ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_INIT_FAILED);
- }
-
-finalize_it:
- RETiRet;
-}
-
-
-/* set the default module load directory. A NULL value may be provided, in
- * which case any previous value is deleted but no new one set. The caller-provided
- * string is duplicated. If it needs to be freed, that's the caller's duty.
- * rgerhards, 2008-03-07
- */
-static rsRetVal
-SetModDir(uchar *pszModDir)
-{
- DEFiRet;
-
- dbgprintf("setting default module load directory '%s'\n", pszModDir);
- if(pModDir != NULL) {
- free(pModDir);
- }
-
- pModDir = (uchar*) strdup((char*)pszModDir);
-
- RETiRet;
-}
-
-
-/* Reference-Counting object access: add 1 to the current reference count. Must be
- * called by anyone interested in using a module. -- rgerhards, 20080-03-10
- */
-static rsRetVal
-Use(char *srcFile, modInfo_t *pThis)
-{
- DEFiRet;
-
- assert(pThis != NULL);
- pThis->uRefCnt++;
- dbgprintf("source file %s requested reference for module '%s', reference count now %u\n",
- srcFile, pThis->pszName, pThis->uRefCnt);
-
-# ifdef DEBUG
- modUsrAdd(pThis, srcFile);
-# endif
-
- RETiRet;
-
-}
-
-
-/* Reference-Counting object access: subract one from the current refcount. Must
- * by called by anyone who no longer needs a module. If count reaches 0, the
- * module is unloaded. -- rgerhards, 20080-03-10
- */
-static rsRetVal
-Release(char *srcFile, modInfo_t **ppThis)
-{
- DEFiRet;
- modInfo_t *pThis;
-
- assert(ppThis != NULL);
- pThis = *ppThis;
- assert(pThis != NULL);
- if(pThis->uRefCnt == 0) {
- /* oops, we are already at 0? */
- dbgprintf("internal error: module '%s' already has a refcount of 0 (released by %s)!\n",
- pThis->pszName, srcFile);
- } else {
- --pThis->uRefCnt;
- dbgprintf("file %s released module '%s', reference count now %u\n",
- srcFile, pThis->pszName, pThis->uRefCnt);
-# ifdef DEBUG
- modUsrDel(pThis, srcFile);
- modUsrPrint(pThis);
-# endif
- }
-
- if(pThis->uRefCnt == 0) {
- /* we have a zero refcount, so we must unload the module */
- dbgprintf("module '%s' has zero reference count, unloading...\n", pThis->pszName);
- modUnlinkAndDestroy(&pThis);
- /* we must NOT do a *ppThis = NULL, because ppThis now points into freed memory!
- * If in doubt, see obj.c::ReleaseObj() for how we are called.
- */
- }
-
- RETiRet;
-
-}
-
-
-/* exit our class
- * rgerhards, 2008-03-11
- */
-BEGINObjClassExit(module, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
-CODESTARTObjClassExit(module)
- /* release objects we no longer need */
- objRelease(errmsg, CORE_COMPONENT);
-
-# ifdef DEBUG
- modUsrPrintAll(); /* debug aid - TODO: integrate with debug.c, at least the settings! */
-# endif
-ENDObjClassExit(module)
-
-
-/* queryInterface function
- * rgerhards, 2008-03-05
- */
-BEGINobjQueryInterface(module)
-CODESTARTobjQueryInterface(module)
- if(pIf->ifVersion != moduleCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->GetNxt = GetNxt;
- pIf->GetNxtType = GetNxtType;
- pIf->GetName = modGetName;
- pIf->GetStateName = modGetStateName;
- pIf->PrintList = modPrintList;
- pIf->UnloadAndDestructAll = modUnloadAndDestructAll;
- pIf->doModInit = doModInit;
- pIf->SetModDir = SetModDir;
- pIf->Load = Load;
- pIf->Use = Use;
- pIf->Release = Release;
-finalize_it:
-ENDobjQueryInterface(module)
-
-
-/* Initialize our class. Must be called as the very first method
- * before anything else is called inside this class.
- * rgerhards, 2008-03-05
- */
-BEGINAbstractObjClassInit(module, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */
- uchar *pModPath;
-
- /* use any module load path specified in the environment */
- if((pModPath = (uchar*) getenv("RSYSLOG_MODDIR")) != NULL) {
- SetModDir(pModPath);
- }
-
- /* now check if another module path was set via the command line (-M)
- * if so, that overrides the environment. Please note that we must use
- * a global setting here because the command line parser can NOT call
- * into the module object, because it is not initialized at that point. So
- * instead a global setting is changed and we pick it up as soon as we
- * initialize -- rgerhards, 2008-04-04
- */
- if(glblModPath != NULL) {
- SetModDir(glblModPath);
- }
-
- /* request objects we use */
- CHKiRet(objUse(errmsg, CORE_COMPONENT));
-ENDObjClassInit(module)
-
-/* vi:set ai:
- */