Exemple #1
0
/* 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;
	uchar *pModDirCurr, *pModDirNext;
	int iLoadCnt;
	struct dlhandle_s *pHandle = NULL;

	assert(pModName != NULL);
	dbgprintf("Requested to load module '%s'\n", pModName);

	pthread_mutex_lock(&mutLoadUnload);

	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);
	}

	pModDirCurr = (uchar *)((pModDir == NULL) ? _PATH_MODDIR : (char *)pModDir);
	pModDirNext = NULL;
	pModHdlr    = NULL;
	iLoadCnt    = 0;
	do {
		/* now build our load module name */
		if(*pModName == '/' || *pModName == '.') {
			*szPath = '\0';	/* we do not need to append the path - its already in the module name */
			iPathLen = 0;
		} else {
			*szPath = '\0';

			iPathLen = strlen((char *)pModDirCurr);
			pModDirNext = (uchar *)strchr((char *)pModDirCurr, ':');
			if(pModDirNext)
				iPathLen = (size_t)(pModDirNext - pModDirCurr);

			if(iPathLen == 0) {
				if(pModDirNext) {
					pModDirCurr = pModDirNext + 1;
					continue;
				}
				break;
			} else if(iPathLen > sizeof(szPath) - 1) {
				errmsg.LogError(0, NO_ERRCODE, "could not load module '%s', module path too long\n", pModName);
				ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_PATHLEN);
			}

			strncat((char *) szPath, (char *)pModDirCurr, iPathLen);
			iPathLen = strlen((char*) szPath);

			if(pModDirNext)
				pModDirCurr = pModDirNext + 1;

			if((szPath[iPathLen - 1] != '/')) {
				if((iPathLen <= sizeof(szPath) - 2)) {
					szPath[iPathLen++] = '/';
					szPath[iPathLen] = '\0';
				} else {
					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);
				}
			}
		}

		/* ... 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(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);
		}

		/* complete load path constructed, so ... GO! */
		dbgprintf("loading module '%s'\n", szPath);

		/* see if we have this one already */
		for (pHandle = pHandles; pHandle; pHandle = pHandle->next) {
			if (!strcmp((char *)pModName, (char *)pHandle->pszName)) {
				pModHdlr = pHandle->pModHdlr;
				break;
			}
		}

		/* not found, try to dynamically link it */
		if (!pModHdlr) {
			pModHdlr = dlopen((char *) szPath, RTLD_NOW);
		}

		iLoadCnt++;
	
	} while(pModHdlr == NULL && *pModName != '/' && pModDirNext);

	if(!pModHdlr) {
		if(iLoadCnt) {
			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));
		}
		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());
		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);
		dlclose(pModHdlr);
		ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_INIT_FAILED);
	}

finalize_it:
	pthread_mutex_unlock(&mutLoadUnload);
	RETiRet;
}
Exemple #2
0
/* 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;
}