Exemplo n.º 1
0
MPlugin * MPluginList::plugin_addload(plid_t plid, const char *fname, PLUG_LOADTIME now)
{
	MPlugin pl_temp;
	MPlugin *pl_found, *pl_added, *pl_loader;

	if ( !(pl_loader=find(plid)) )
	{
		META_DEBUG(1, ("Couldn't find plugin that gave this loading request!"));
		RETURN_ERRNO(NULL, ME_BADREQ);
	}

	memset(&pl_temp, 0, sizeof(pl_temp));

	if (!pl_temp.plugin_parseline(fname, pl_loader->index))
	{
		RETURN_ERRNO(NULL, ME_NOTFOUND);
	}

	if (pl_temp.resolve() != mTRUE)
	{
		META_DEBUG(1, ("Couldn't resolve given path into a file: %s", pl_temp.file));
		RETURN_ERRNO(NULL, ME_NOTFOUND);
	}

	if ( (pl_found=find(pl_temp.pathname)) )
	{
		META_DEBUG(1, ("Plugin '%s' already in current list; file=%s desc='%s'", 
				pl_temp.file, pl_found->file, pl_found->desc));
		RETURN_ERRNO(NULL, ME_ALREADY);
	}

	if (!(pl_added=add(&pl_temp)))
	{
		META_DEBUG(1, ("Couldn't add plugin '%s' to list; see log", pl_temp.desc));
		return NULL;
	}

	pl_added->action = PA_LOAD;
	if (!pl_added->load(now))
	{
		if (meta_errno==ME_NOTALLOWED || meta_errno==ME_DELAYED)
		{
			META_DEBUG(1, ("Plugin '%s' couldn't attach; only allowed %s", 
					pl_added->desc, pl_added->str_loadable(SL_ALLOWED)));
			pl_added->clear();
		} else if (pl_added->status == PL_OPENED) {
			META_DEBUG(1, ("Opened plugin '%s', but failed to attach; see log", pl_added->desc));
		} else {
			META_DEBUG(1, ("Couldn't load plugin '%s'; see log", pl_added->desc));
		}
		return NULL;
	}

	META_DEBUG(1, ("Loaded plugin '%s' successfully", pl_added->desc));
	meta_errno = ME_NOERROR;

	return pl_added;
}
Exemplo n.º 2
0
// Allow plugins to call the entity functions in the GameDLL.  In
// particular, calling "player()" as needed by most Bots.  Suggested by
// Jussi Kivilinna.
qboolean mutil_CallGameEntity(plid_t plid, const char *entStr, entvars_t *pev) {
	plugin_info_t *plinfo;
	ENTITY_FN pfnEntity;

	plinfo=(plugin_info_t *)plid;
	META_DEBUG(8, ("Looking up game entity '%s' for plugin '%s'", entStr,
				plinfo->name));
	pfnEntity = (ENTITY_FN) DLSYM(GameDLL.handle, entStr);
	if(!pfnEntity) {
		META_ERROR("Couldn't find game entity '%s' in game DLL '%s' for plugin '%s'", entStr, GameDLL.name, plinfo->name);
		return(false);
	}
	META_DEBUG(7, ("Calling game entity '%s' for plugin '%s'", entStr,
				plinfo->name));
	(*pfnEntity)(pev);
	return(true);
}
Exemplo n.º 3
0
MPlugin *MPluginList::find(const char *findpath) {
	int i;

	if(!findpath)
		RETURN_ERRNO(NULL, ME_ARGUMENT);
	META_DEBUG(8, ("Looking for loaded plugin with dlfnamepath: %s", findpath));
	for(i=0; i < endlist; i++) {
		META_DEBUG(9, ("Looking at: plugin %s loadedpath: %s", plist[i].file, plist[i].pathname));
		if(plist[i].status < PL_VALID)
			continue;
		if(strmatch(plist[i].pathname, findpath)) {
			META_DEBUG(8, ("Found loaded plugin %s", plist[i].file));
			return(&plist[i]);
		}
	}
	META_DEBUG(8, ("No loaded plugin found with path: %s", findpath));
	RETURN_ERRNO(NULL, ME_NOTFOUND);
}
Exemplo n.º 4
0
void do_link_ent(ENTITY_FN *pfnEntity, int *missing, char *entStr, 
		entvars_t *pev)
{;
	if(*missing) {
		META_DEBUG(9, ("Skipping entity '%s'; was previously found missing", entStr));
		return;
	}
	if(!*pfnEntity) {
		META_DEBUG(9, ("Looking up game entity '%s'", entStr));
		*pfnEntity = (ENTITY_FN) DLSYM(GameDLL.handle, entStr);
	}
	if(!*pfnEntity) {
		META_ERROR("Couldn't find game entity '%s' in game DLL '%s': %s", entStr, GameDLL.name, DLERROR());
		*missing=1;
		return;
	}
	META_DEBUG(8, ("Linking game entity '%s'", entStr));
	(*pfnEntity)(pev);
}
Exemplo n.º 5
0
mBOOL DLLINTERNAL MConfig::load(const char *fn) {
	FILE *fp;
	char loadfile[PATH_MAX];
	char line[MAX_CONF_LEN];
	char *optname, *optval;
	option_t *optp;
	int ln;

	// Make full pathname (from gamedir if relative, collapse "..",
	// backslashes, etc).
	full_gamedir_path(fn, loadfile);

	fp=fopen(loadfile, "r");
	if(!fp) {
		META_WARNING("unable to open config file '%s': %s", loadfile, 
				strerror(errno));
		RETURN_ERRNO(mFALSE, ME_NOFILE);
	}

	META_DEBUG(2, ("Loading from config file: %s", loadfile));
	for(ln=1; !feof(fp) && fgets(line, sizeof(line), fp); ln++) {
		if(line[0]=='#')
			continue;
		if(line[0]==';')
			continue;
		if(strnmatch(line, "//", 2))
			continue;
		if(!(optname=strtok(line, " \t\r\n"))) {
			META_WARNING("'%s' line %d: bad config format: missing option", 
					loadfile, ln);
			continue;
		}
		if(!(optval=strtok(NULL, "\r\n"))) {
			META_WARNING("'%s' line %d: bad config format: missing value", 
					loadfile, ln);
			continue;
		}

		if(!(optp=find(optname))) {
			META_WARNING("'%s' line %d: unknown option name '%s'", 
					loadfile, ln, optname);
			continue;
		}

		if(!set(optp, optval)) {
			META_WARNING("'%s' line %d: unable to set option '%s' value '%s'", 
					loadfile, ln, optname, optval);
			continue;
		}
	}
	filename=strdup(loadfile);
	fclose(fp);
	return(mTRUE);
}
Exemplo n.º 6
0
MPlugin *MPluginList::find_memloc(void *memptr) {
	const char *dlfile;

	if(!memptr)
		RETURN_ERRNO(NULL, ME_ARGUMENT);
	if(!(dlfile=DLFNAME(memptr))) {
		META_DEBUG(8, ("DLFNAME failed to find memloc %d", memptr));
		// meta_errno should be already set in DLFNAME
		return(NULL);
	}
	return(find(dlfile));
}
Exemplo n.º 7
0
int valid_gamedir_file(char *path) {
	char buf[PATH_MAX];
	struct stat st;
	int ret, reg, size;

	if(!path)
		return(FALSE);

	if(strmatch(path, "/dev/null"))
		return(TRUE);

	if(is_absolute_path(path))
		STRNCPY(buf, path, sizeof(buf));
	else
		snprintf(buf, sizeof(buf), "%s/%s", GameDLL.gamedir, path);

	ret=stat(buf, &st);
	if(ret != 0) {
		META_DEBUG(5, ("Unable to stat '%s': %s", buf, strerror(errno)));
		return(FALSE);
	}

	reg=S_ISREG(st.st_mode);
	if(!reg) {
		META_DEBUG(5, ("Not a regular file: %s", buf));
		return(FALSE);
	}

	size=st.st_size;
	if(!size) {
		META_DEBUG(5, ("Empty file: %s", buf));
		return(FALSE);
	}

	if(ret==0 && reg && size)
		return(TRUE);
	else
		return(FALSE);
}
Exemplo n.º 8
0
// Find a usermsg, registered by the gamedll, with the corresponding
// msgname, and return remaining info about it (msgid, size).
int mutil_GetUserMsgID(plid_t plid, const char *msgname, int *size) {
	plugin_info_t *plinfo;
	MRegMsg *umsg;

	plinfo=(plugin_info_t *)plid;
	META_DEBUG(8, ("Looking up usermsg name '%s' for plugin '%s'", msgname,
				plinfo->name));
	umsg=RegMsgs->find(msgname);
	if(umsg) {
		if(size)
			*size=umsg->size;
		return(umsg->msgid);
	}
	else
		return(0);
}
Exemplo n.º 9
0
// Add the given cvar name to the list and return the instance.  This only
// writes the "name" to the new cvar; other fields are written with
// cvar::set().
// meta_errno values:
//  - ME_NOMEM			couldn't alloc or realloc for various parts
MRegCvar * DLLINTERNAL MRegCvarList::add(const char *addname) {
	MRegCvar *icvar;

	if(endlist==size) {
		// grow array
		MRegCvar *temp;
		int i, newsize;
		newsize=size+REG_CVAR_GROWSIZE;
		META_DEBUG(6, ("Growing reg cvar list from %d to %d", size, newsize));
		temp = (MRegCvar *) realloc(vlist, newsize*sizeof(MRegCvar));
		if(!temp) {
			META_WARNING("Couldn't grow registered cvar list to %d for '%s'; %s", newsize, addname, strerror(errno));
			RETURN_ERRNO(NULL, ME_NOMEM);
		}
		vlist=temp;
		size=newsize;
		// initialize new (unused) entries
		for(i=endlist; i<size; i++) {
			memset(&vlist[i], 0, sizeof(vlist[i]));
			vlist[i].init(i+1);		// 1-based
		}
	}

	icvar = &vlist[endlist];

	// Malloc space for the cvar and cvar name, for two reasons:
	//  - Can't point to memory loc in plugin (another segv waiting to 
	//    happen).
	//  - Can't point to memory in vlist which might get moved later by 
	//    realloc (again, segv).
	icvar->data = (cvar_t *) calloc(1, sizeof(cvar_t));
	if(!icvar->data) {
		META_WARNING("Couldn't malloc cvar for adding reg cvar name '%s': %s", 
				addname, strerror(errno));
		RETURN_ERRNO(NULL, ME_NOMEM);
	}
	icvar->data->name=strdup(addname);
	if(!icvar->data->name) {
		META_WARNING("Couldn't strdup for adding reg cvar name '%s': %s", 
				addname, strerror(errno));
		RETURN_ERRNO(NULL, ME_NOMEM);
	}
	endlist++;
	
	return(icvar);
}
Exemplo n.º 10
0
// able to store a string of PATH_MAX length.
char *full_gamedir_path(const char *path, char *fullpath) {
	char buf[PATH_MAX];

	// Build pathname from filename, plus gamedir if relative path.
	if(is_absolute_path(path))
		STRNCPY(buf, path, sizeof(buf));
	else
		snprintf(buf, sizeof(buf), "%s/%s", GameDLL.gamedir, path);
	// Remove relative path components, if possible.
	if(!realpath(buf, fullpath)) {
		META_DEBUG(4, ("Unable to get realpath for '%s': %s", buf,
				str_os_error()));
		STRNCPY(fullpath, path, PATH_MAX);
	}
	// Replace backslashes, etc.
	normalize_pathname(fullpath);
	return(fullpath);
}
Exemplo n.º 11
0
// Find a usermsg, registered by the gamedll, with the corresponding
// msgid, and return remaining info about it (msgname, size).
const char *mutil_GetUserMsgName(plid_t plid, int msgid, int *size) {
	plugin_info_t *plinfo;
	MRegMsg *umsg;

	plinfo=(plugin_info_t *)plid;
	META_DEBUG(8, ("Looking up usermsg id '%d' for plugin '%s'", msgid,
				plinfo->name));
	// Guess names for any built-in Engine messages mentioned in the SDK;
	// from dlls/util.h.
	if(msgid < 64) {
		switch(msgid) {
			case SVC_TEMPENTITY:
				if(size) *size=-1;
				return("tempentity?");
			case SVC_INTERMISSION:
				if(size) *size=-1;
				return("intermission?");
			case SVC_CDTRACK:
				if(size) *size=-1;
				return("cdtrack?");
			case SVC_WEAPONANIM:
				if(size) *size=-1;
				return("weaponanim?");
			case SVC_ROOMTYPE:
				if(size) *size=-1;
				return("roomtype?");
			case SVC_DIRECTOR:
				if(size) *size=-1;
				return("director?");
		}
	}
	umsg=RegMsgs->find(msgid);
	if(umsg) {
		if(size)
			*size=umsg->size;
		// 'name' is assumed to be a constant string, allocated in the
		// gamedll.
		return(umsg->name);
	}
	else
		return(NULL);
}
Exemplo n.º 12
0
// Try to call the function.  Relies on OS-specific routine to attempt
// calling the function without generating a segfault from an unloaded
// plugin DLL.
// meta_errno values:
//  - ME_BADREQ		function disabled/invalid
//  - ME_ARGUMENT	function pointer is null
mBOOL DLLINTERNAL MRegCmd::call(void) {
	mBOOL ret;

	// can we expect to call this function?
	if(status != RG_VALID)
		RETURN_ERRNO(mFALSE, ME_BADREQ);
	if(!pfnCmd)
		RETURN_ERRNO(mFALSE, ME_ARGUMENT);

	// try to call this function
	ret=os_safe_call(pfnCmd);
	if(!ret) {
		META_DEBUG(4, ("Plugin reg_cmd '%s' called after unloaded; removed from list", name));
		status=RG_INVALID;
		pfnCmd=NULL;
		// NOTE: we can't free the malloc'd space for the name, as that
		// would just re-introduce the segfault problem..
	}
	// meta_errno (if failed) is set already in os_safe_call()
	return(ret);
}
Exemplo n.º 13
0
// Add the given name to the list and return the instance.  This only
// writes the "name" to the new cmd; other fields are writtin by caller
// (meta_AddServerCommand).
// meta_errno values:
//  - ME_NOMEM			couldn't realloc or malloc for various parts
MRegCmd * DLLINTERNAL MRegCmdList::add(const char *addname) {
	MRegCmd *icmd;

	if(endlist==size) {
		// grow array
		MRegCmd *temp;
		int i, newsize;
		newsize=size+REG_CMD_GROWSIZE;
		META_DEBUG(6, ("Growing reg cmd list from %d to %d", size, newsize));
		temp = (MRegCmd *) realloc(mlist, newsize*sizeof(MRegCmd));
		if(!temp) {
			META_WARNING("Couldn't grow registered command list to %d for '%s': %s", newsize, addname, strerror(errno));
			RETURN_ERRNO(NULL, ME_NOMEM);
		}
		mlist=temp;
		size=newsize;
		// initialize new (unused) entries
		for(i=endlist; i<size; i++) {
			memset(&mlist[i], 0, sizeof(mlist[i]));
			mlist[i].init(i+1);		// 1-based
		}
	}
	icmd = &mlist[endlist];

	// Malloc space separately for the command name, because:
	//  - Can't point to memory loc in plugin (another segv waiting to 
	//    happen).
	//  - Can't point to memory in mlist which might get moved later by 
	//    realloc (again, segv).
	icmd->name=strdup(addname);
	if(!icmd->name) {
		META_WARNING("Couldn't strdup for adding reg cmd name '%s': %s", 
				addname, strerror(errno));
		RETURN_ERRNO(NULL, ME_NOMEM);
	}
	endlist++;
	
	return(icmd);
}
mBOOL DLLINTERNAL is_gamedll(const char *filename) {
	HANDLE hFile;
	HANDLE hMap;
	void * mapview;
	IMAGE_NT_HEADERS * ntheaders;
	IMAGE_SECTION_HEADER * sections;
	int num_sects;
	IMAGE_EXPORT_DIRECTORY * exports;

	int has_GiveFnptrsToDll = 0;
	int has_GetEntityAPI2 = 0;
	int has_GetEntityAPI = 0;

	// Try open file for read
	hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(is_invalid_handle(hFile)) {
		META_DEBUG(3, ("is_gamedll(%s): CreateFile() failed.", filename));
		return(mFALSE);
	}
	
	//
	hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
	if(is_invalid_handle(hMap)) {
		META_DEBUG(3, ("is_gamedll(%s): CreateFileMapping() failed.", filename));
		CloseHandle(hFile);
		return(mFALSE);
	}
	
	//
	mapview = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
	if(!mapview) {
		META_DEBUG(3, ("is_gamedll(%s): MapViewOfFile() failed.", filename));
		CloseHandle(hMap);
		CloseHandle(hFile);
		return(mFALSE);
	}
	
	ntheaders = get_ntheaders(mapview);
	if(!ntheaders) {
		META_DEBUG(3, ("is_gamedll(%s): get_ntheaders() failed.", filename));
		UnmapViewOfFile(mapview);
		CloseHandle(hMap);
		CloseHandle(hFile);
		return(mFALSE);
	}
	
	//Sections for va_to_mapaddr function
	sections = IMAGE_FIRST_SECTION(ntheaders);
	num_sects = ntheaders->FileHeader.NumberOfSections;
	if(IsBadReadPtr(sections, num_sects * sizeof(IMAGE_SECTION_HEADER))) {
		META_DEBUG(3, ("is_gamedll(%s): IMAGE_FIRST_SECTION() failed.", filename));
		UnmapViewOfFile(mapview);
		CloseHandle(hMap);
		CloseHandle(hFile);
		return(mFALSE);
	}
	
	//
	exports = get_export_table(mapview, ntheaders, sections, num_sects);
	if(!exports) {
		META_DEBUG(3, ("is_gamedll(%s): get_export_table() failed.", filename));
		UnmapViewOfFile(mapview);
		CloseHandle(hMap);
		CloseHandle(hFile);
		return(mFALSE);
	}
	
	//
	unsigned long * names = (unsigned long *)va_to_mapaddr(mapview, sections, num_sects, exports->AddressOfNames);
	if(IsBadReadPtr(names, exports->NumberOfNames * sizeof(unsigned long))) {
		META_DEBUG(3, ("is_gamedll(%s): Pointer to exported function names is invalid.", filename));
		UnmapViewOfFile(mapview);
		CloseHandle(hMap);
		CloseHandle(hFile);
		return(mFALSE);
	}
	
	for(unsigned int i = 0; i < exports->NumberOfNames; i++) {
		//get function name with valid address
		char * funcname = (char *)va_to_mapaddr(mapview, sections, num_sects, names[i]);
		if(IsBadStringPtrA(funcname, 128))
			continue;
		
		// Check
		// Fast check for 'G' first
		if(funcname[0] == 'G') {
			// Collect export information
			if(!has_GiveFnptrsToDll)
				has_GiveFnptrsToDll = strmatch(funcname, "GiveFnptrsToDll");
			if(!has_GetEntityAPI2)
				has_GetEntityAPI2   = strmatch(funcname, "GetEntityAPI2");
	  		if(!has_GetEntityAPI)
	  			has_GetEntityAPI    = strmatch(funcname, "GetEntityAPI");
	  	}
		// Check if metamod plugin
		else if(funcname[0] == 'M') {
			if(strmatch(funcname, "Meta_Init") || 
			   strmatch(funcname, "Meta_Query") || 
			   strmatch(funcname, "Meta_Attach") || 
			   strmatch(funcname, "Meta_Detach")) {
				// Metamod plugin.. is not gamedll
				META_DEBUG(5, ("is_gamedll(%s): Detected Metamod plugin, library exports [%s].", filename, funcname));
		   		
				UnmapViewOfFile(mapview);
				CloseHandle(hMap);
				CloseHandle(hFile);
				
				return(mFALSE);
			}
		}
	}
	
	UnmapViewOfFile(mapview);
	CloseHandle(hMap);
	CloseHandle(hFile);
	
	// Check if gamedll
	if(has_GiveFnptrsToDll && (has_GetEntityAPI2 || has_GetEntityAPI)) {
		// This is gamedll!
		META_DEBUG(5, ("is_gamedll(%s): Detected GameDLL.", filename));

		return(mTRUE);
	} else {
		META_DEBUG(5, ("is_gamedll(%s): Library isn't GameDLL.", filename));
		
		return(mFALSE);
	}
}
Exemplo n.º 15
0
mBOOL MPluginList::refresh(PLUG_LOADTIME now) {
	int i, ndone=0, nkept=0, nloaded=0, nunloaded=0, nreloaded=0, ndelayed=0;
	MPlugin *iplug;

	if (!ini_refresh()) {
		META_ERROR("dll: Problem reloading plugins.ini: %s", inifile);
		// meta_errno should be already set in ini_refresh()
		return(mFALSE);
	}

	META_LOG("dll: Updating plugins...");
	for(i=0; i < endlist; i++) {
		iplug=&plist[i];
		if(iplug->status < PL_VALID)
			continue;
		switch(iplug->action) {
			case PA_KEEP:
				META_DEBUG(1, ("Keeping plugin '%s'", iplug->desc));
				iplug->action=PA_NONE;
				nkept++;
				break;
			case PA_LOAD:
				META_DEBUG(1, ("Loading plugin '%s'", iplug->desc));
				if(iplug->load(now))
					nloaded++;
				else if(meta_errno==ME_DELAYED)
					ndelayed++;
				break;
			case PA_RELOAD:
				META_DEBUG(1, ("Reloading plugin '%s'", iplug->desc));
				if(iplug->reload(now, PNL_FILE_NEWER))
					nreloaded++;
				else if(meta_errno==ME_DELAYED)
					ndelayed++;
				break;
			case PA_NONE:
				// If previously loaded from ini, but apparently removed from new ini.
				if(iplug->source==PS_INI && iplug->status >= PL_RUNNING) {
					META_DEBUG(1, ("Unloading plugin '%s'", iplug->desc));
					iplug->action=PA_UNLOAD;
					if(iplug->unload(now, PNL_INI_DELETED, PNL_INI_DELETED))
						nunloaded++;
					else if(meta_errno==ME_DELAYED)
						ndelayed++;
				}
				break;
			case PA_ATTACH:
				// Previously requested attach, but was delayed?
				META_DEBUG(1, ("Retrying attach plugin '%s'", iplug->desc));
				if(iplug->retry(now, PNL_DELAYED))
					nloaded++;
				else if(meta_errno==ME_DELAYED)
					ndelayed++;
				break;
			case PA_UNLOAD:
				// Previously requested unload, but was delayed?
				META_DEBUG(1, ("Retrying unload plugin '%s'", iplug->desc));
				if(iplug->retry(now, PNL_DELAYED))
					nunloaded++;
				else if(meta_errno==ME_DELAYED)
					ndelayed++;
				break;
			case PA_NULL:
				META_ERROR("dll: Unexpected action for plugin '%s': '%s'", iplug->desc, iplug->str_action());
				break;
			default:
				META_ERROR("dll: Unrecognized action for plugin '%s': '%s'", iplug->desc, iplug->str_action());
				break;
		}
		ndone++;
	}
	META_LOG("dll: Finished updating %d plugins; kept %d, loaded %d, unloaded %d, reloaded %d, delayed %d", 
			ndone, nkept, nloaded, nunloaded, nreloaded, ndelayed);
	return(mTRUE);
}
Exemplo n.º 16
0
mBOOL MPluginList::ini_refresh() {
	FILE *fp;
	char line[MAX_STRBUF_LEN];
	int n, ln;
	MPlugin pl_temp;
	MPlugin *pl_found, *pl_added;

	fp=fopen(inifile, "r");
	if(!fp) {
		META_ERROR("ini: Unable to open plugins file '%s': %s", inifile, 
				strerror(errno));
		RETURN_ERRNO(mFALSE, ME_NOFILE);
	}

	META_LOG("ini: Begin re-reading plugins list: %s", inifile);
	for(n=0, ln=1; 
			!feof(fp) && fgets(line, sizeof(line), fp) && n < size; 
			ln++) 
	{
		// Remove line terminations.
		char *cp;
		if((cp=strrchr(line, '\r')))
			*cp='\0';
		if((cp=strrchr(line, '\n')))
			*cp='\0';
		// Parse into a temp plugin
		memset(&pl_temp, 0, sizeof(pl_temp));
		if(!pl_temp.ini_parseline(line)) {
			if(meta_errno==ME_FORMAT)
				META_ERROR("ini: Skipping malformed line %d of %s", 
						ln, inifile);
			continue;
		}
		// Try to find plugin with this pathname in the current list of
		// plugins.
		if(!(pl_found=find(pl_temp.pathname))) {
			// Check for a matching platform with higher platform specifics
			// level.
			if(NULL != (pl_found=find_match(&pl_temp))) {
				if(pl_found->pfspecific >= pl_temp.pfspecific) {
					META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)",
                       		 ln, inifile, pl_found->pfspecific, pl_temp.pfspecific)); 
					continue;
				}
				if(PA_LOAD == pl_found->action) {
					META_DEBUG(1, ("ini: Plugin in line %d overrides loading of plugin with lower platform specific level %d, ours %d",
								ln, pl_found->pfspecific, pl_temp.pfspecific));
					int _index = pl_found->index;
					memset(pl_found, 0, sizeof(MPlugin));
					pl_found->index = _index;
				}
				else {
					META_DEBUG(1, ("ini: Plugin in line %d should override existing plugin with lower platform specific level %d, ours %d. Unable to comply.",
								ln, pl_found->pfspecific, pl_temp.pfspecific));
					continue;
				}
			}
			// new plugin; add to list
			if((pl_added=add(&pl_temp))) {
				// try to load this plugin at the next opportunity
				pl_added->action=PA_LOAD;
			}
			else
				// error details logged in add()
				continue;
		}
		else {
			// This plugin is already in the current list of plugins.
			// Pathname already matches.  Recopy desc, if specified in
			// plugins.ini.
			if(pl_temp.desc[0] != '<')
				STRNCPY(pl_found->desc, pl_temp.desc, sizeof(pl_found->desc));

			// Check the file to see if it looks like it's been modified
			// since we last loaded it.
			if(!pl_found->newer_file()) {
				if(meta_errno==ME_NOFILE) {
					META_ERROR("ini: Skipping plugin, couldn't stat file '%s': %s",
							pl_found->pathname, strerror(errno));
					continue;
				}
				else {
					// File hasn't been updated.
					// Keep plugin (don't let refresh() unload it).
					pl_found->action=PA_KEEP;
				}
			}
			// Newer file on disk.
			else if(pl_found->status >= PL_OPENED)  {
				META_DEBUG(2, ("ini: Plugin '%s' has newer file on disk", pl_found->desc));
				pl_found->action=PA_RELOAD;
			}
			else
				META_ERROR("ini: Plugin '%s' has newer file, but unexpected status (%s)",
						pl_found->desc, pl_found->str_status());
		}
		if(NULL != pl_found) {
			META_LOG("ini: Read plugin config for: %s", pl_found->desc);
		}
		else {
			META_LOG("ini: Read plugin config for: %s", pl_temp.desc);
		}
		n++;
	}
	META_LOG("ini: Finished reading plugins list: %s; Found %d plugins", inifile, n);

	fclose(fp);
	if(!n) {
		META_ERROR("ini: Warning; no plugins found to load?");
	}
	return(mTRUE);
}
Exemplo n.º 17
0
mBOOL MPluginList::ini_startup() {
	FILE *fp;
	char line[MAX_STRBUF_LEN];
	int n, ln;
	MPlugin *pmatch;

	if(!valid_gamedir_file(inifile)) {
		META_ERROR("ini: Metamod plugins file empty or missing: %s", inifile);
		RETURN_ERRNO(mFALSE, ME_NOFILE);
	}
	full_gamedir_path(inifile, inifile);

	fp=fopen(inifile, "r");
	if(!fp) {
		META_ERROR("ini: Unable to open plugins file '%s': %s", inifile, 
				strerror(errno));
		RETURN_ERRNO(mFALSE, ME_NOFILE);
	}

	META_LOG("ini: Begin reading plugins list: %s", inifile);
	for(n=0, ln=1; 
			!feof(fp) && fgets(line, sizeof(line), fp) && n < size; 
			ln++) 
	{
		// Remove line terminations.
		char *cp;
		if((cp=strrchr(line, '\r')))
			*cp='\0';
		if((cp=strrchr(line, '\n')))
			*cp='\0';
		// Parse directly into next entry in array
		if(!plist[n].ini_parseline(line)) {
			if(meta_errno==ME_FORMAT)
				META_ERROR("ini: Skipping malformed line %d of %s", ln, 
						inifile);
			continue;
		}
		// Check for a duplicate - an existing entry with this pathname.
		if(find(plist[n].pathname)) {
			// Should we check platform specific level here?
			META_INFO("ini: Skipping duplicate plugin, line %d of %s: %s", 
					ln, inifile, plist[n].pathname);
			continue;
		}
		// Check for a matching platform with different platform specifics
		// level.
		if(NULL != (pmatch=find_match(&plist[n]))) {
			if(pmatch->pfspecific >= plist[n].pfspecific) {
				META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)",
                         ln, inifile, pmatch->pfspecific, plist[n].pfspecific)); 
				continue;
			}
			META_DEBUG(1, ("ini: Plugin in line %d overrides existing plugin with lower platform specific level %d, ours %d",
					ln, pmatch->pfspecific, plist[n].pfspecific));
			int _index = pmatch->index;
			memset(pmatch, 0, sizeof(MPlugin));
			pmatch->index = _index;
		}
		plist[n].action=PA_LOAD;
		META_LOG("ini: Read plugin config for: %s", plist[n].desc);
		n++;
		endlist=n;		// mark end of list
	}
	META_LOG("ini: Finished reading plugins list: %s; Found %d plugins to load",
			inifile, n);

	fclose(fp);
	if(!n) {
		META_ERROR("ini: Warning; no plugins found to load?");
	}
	return(mTRUE);
}
Exemplo n.º 18
0
mBOOL DLLINTERNAL MConfig::set(option_t *setp, const char *setstr) {
	char pathbuf[PATH_MAX];
	int *optval = (int *) setp->dest;
	char **optstr = (char **) setp->dest;
	// cvar_t *optcvar = (cvar_t *) setp->dest;
	// SETOPT_FN optcmd = (SETOPT_FN) setp->dest;

	if(!setstr)
		return(mTRUE);

	switch(setp->type) {
		case CF_INT:
			if(!isdigit(setstr[0])) {
				META_WARNING("option '%s' invalid format '%s'", setp->name, setstr);
				RETURN_ERRNO(mFALSE, ME_FORMAT);
			}
			*optval=atoi(setstr);
			META_DEBUG(3, ("set config int: %s = %d", setp->name, *optval));
			break;
		case CF_BOOL:
			if(strcasematch(setstr, "true")
					|| strcasematch(setstr, "yes")
					|| strmatch(setstr, "1"))
			{
				*optval=1;
			}
			else if(strcasematch(setstr, "false")
					|| strcasematch(setstr, "no")
					|| strmatch(setstr, "0"))
			{
				*optval=0;
			}
			else {
				META_WARNING("option '%s' invalid format '%s'", setp->name, setstr);
				RETURN_ERRNO(mFALSE, ME_FORMAT);
			}
			META_DEBUG(3, ("set config bool: %s = %s", setp->name, *optval ? "true" : "false"));
			break;
		case CF_STR:
			if(*optstr)
				free(*optstr);
			*optstr=strdup(setstr);
			META_DEBUG(3, ("set config string: %s = %s", setp->name, *optstr));
			break;
		case CF_PATH:
			if(*optstr)
				free(*optstr);
			full_gamedir_path(setstr, pathbuf);
			*optstr=strdup(pathbuf);
			META_DEBUG(3, ("set config path: %s = %s", setp->name, *optstr));
			break;
#if 0
		case CF_CVAR:
			CVAR_SET_STRING(optcvar->name, setstr);
			META_DEBUG(3, ("set config cvar: %s = %s", optcvar->name, setstr));
			break;
		case CF_CMD:
			optcmd(setp->name, setstr);
			META_DEBUG(3, ("set config command: %s, %s", optcvar->name, setstr));
			break;
#endif
		default:
			META_WARNING("unrecognized config type '%d'", setp->type);
			RETURN_ERRNO(mFALSE, ME_ARGUMENT);
	}
	return(mTRUE);
}