예제 #1
0
int mm_RegUserMsg(const char *pszName, int iSize) {
	int imsgid;
	MRegMsg *nmsg=NULL;
	META_ENGINE_HANDLE(int, 0, FN_REGUSERMSG, pfnRegUserMsg, (pszName, iSize));
	// Expand the macro, since we need to do extra work.
	/// RETURN_API()
	if (--CALL_API_count>0)
		/*Restore backup*/
		PublicMetaGlobals = backup_meta_globals;
	if(status==MRES_OVERRIDE) {
		META_DEBUG(loglevel, ("Returning (override) %s()", pfn_string));
		imsgid=override_ret;
	}
	else
		imsgid=orig_ret;
	// Add the msgid, name, and size to our saved list, if we haven't
	// already.
	nmsg=RegMsgs->find(imsgid);
	if(nmsg) {
		if(FStrEq(pszName, nmsg->name))
			// This name/msgid pair was already registered.
			META_DEBUG(3, ("user message registered again: name=%s, msgid=%d", pszName, imsgid));
		else
			// This msgid was previously used by a different message name.
			META_ERROR("user message id reused: msgid=%d, oldname=%s, newname=%s", imsgid, nmsg->name, pszName);
	}
	else
		RegMsgs->add(pszName, imsgid, iSize);
	return(imsgid);
}
예제 #2
0
mBOOL MHook::enqueue(MFuncQueue *mfq, event_args_t *args, const char *logline) {

    func_item_t *fp;



    if(!mfq || !args || !logline)

        RETURN_ERRNO(mFALSE, ME_ARGUMENT);



    fp = (func_item_t *) malloc(sizeof(func_item_t));

    if(!fp) {

        META_ERROR("malloc failed for func_item_t");

        RETURN_ERRNO(mFALSE, ME_NOMEM);

    }

    fp->hook=this;

    fp->evargs=args;

    fp->logline=logline;

    mfq->push(fp);

    return(mTRUE);

}
예제 #3
0
void mm_AlertMessage(ALERT_TYPE atype, char *szFmt, ...) {
#ifndef UNFINISHED
	META_ENGINE_HANDLE_void_varargs(FN_ALERTMESSAGE, pfnAlertMessage, atype, szFmt);
#else /* UNFINISHED */
	// Expand macro, since we need to do extra work here.

	// usual setup
	SETUP_API_CALLS_void(FN_ALERTMESSAGE, pfnAlertMessage, engine_info);
	char buf[MAX_STRBUF_LEN];
	va_list ap;
	int len;
	char *qmsg;
	META_DEBUG(loglevel, ("In %s: fmt=%s", pfn_string, szFmt));
	va_start(ap, szFmt);
	len=vsnprintf(buf, sizeof(buf), szFmt, ap) + 1;
	va_end(ap);
	// pass logmsg string to log parsing thread
	/// qmsg=strdup(buf);
	qmsg=(char *) malloc(len * sizeof(char));
	if(!qmsg)
		META_ERROR("malloc failed for logmsg to thread queue");
	else {
		STRNCPY(qmsg, buf, len);
		LogQueue->push(qmsg);
	}
	// usual passing to plugins/engine
	CALL_PLUGIN_API_void(P_PRE, pfnAlertMessage, (atype, "%s", buf), engine_table);
	CALL_ENGINE_API_void(pfnAlertMessage, (atype, "%s", buf));
	CALL_PLUGIN_API_void(P_POST, pfnAlertMessage, (atype, "%s", buf), engine_post_table);
#endif /* UNFINISHED */

	// usual return.
	RETURN_API_void()
}
예제 #4
0
파일: mutil.cpp 프로젝트: ET-NiK/amxxgroup
// Return various string-based info about the game/MOD/gamedll.
const char *mutil_GetGameInfo(plid_t plid, ginfo_t type) {
	static char buf[MAX_STRBUF_LEN];
	const char *cp;
	switch(type) {
		case GINFO_NAME:
			cp=GameDLL.name;
			break;
		case GINFO_DESC:
			cp=GameDLL.desc;
			break;
		case GINFO_GAMEDIR:
			cp=GameDLL.gamedir;
			break;
		case GINFO_DLL_FULLPATH:
			cp=GameDLL.pathname;
			break;
		case GINFO_DLL_FILENAME:
			cp=GameDLL.file;
			break;
		default:
			META_ERROR("GetGameInfo: invalid request '%d' from plugin '%s'",
					type, plid->name);
			return(NULL);
	}
	STRNCPY(buf, cp, sizeof(buf));
	return(buf);
}
예제 #5
0
파일: mutil.cpp 프로젝트: ET-NiK/amxxgroup
// Return the full path of the plugin's loaded dll/so file.
const char *mutil_GetPluginPath(plid_t plid) {
	static char buf[PATH_MAX];
	MPlugin *plug;

	plug=Plugins->find(plid);
	if(!plug) {
		META_ERROR("GetPluginPath: couldn't find plugin '%s'",
				plid->name);
		return(NULL);
	}
	STRNCPY(buf, plug->pathname, sizeof(buf));
	return(buf);
}
예제 #6
0
mBOOL MPluginList::load() {
	int i, n;

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

	META_LOG("dll: Loading plugins...");
	for(i=0, n=0; i < endlist; i++) {
		if(plist[i].status < PL_VALID)
			continue;
		if(plist[i].load(PT_STARTUP) == mTRUE)
			n++;
		else
			// all plugins should be loadable at startup...
			META_ERROR("dll: Failed to load plugin '%s'", plist[i].file);
	}
	META_LOG("dll: Finished loading %d plugins", n);
	return(mTRUE);
}
예제 #7
0
// Start the log parsing thread.
void startup_logparse_thread(void) {
	int ret;

	LogQueue = new MLogmsgQueue(MAX_QUEUE_SIZE);
	HookQueue = new MFuncQueue(MAX_QUEUE_SIZE);

	ret=THREAD_CREATE(&logparse_thread_id, logparse_handler);
	if(ret != THREAD_OK) {
		// For now, we just exit if this fails.
		META_ERROR("Couldn't start thread for log parsing!  Exiting...");
		do_exit(1);
	}
}
예제 #8
0
파일: mutil.cpp 프로젝트: ET-NiK/amxxgroup
// 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);
}
예제 #9
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);
}
예제 #10
0
MPlugin *MPluginList::add(MPlugin *padd) {
	int i;
	MPlugin *iplug;

	// Find either:
	//  - a slot in the list that's not being used
	//  - the end of the list
	for(i=0; i < endlist && plist[i].status != PL_EMPTY; i++);

	// couldn't find a slot to use
	if(i==size) {
		META_ERROR("Couldn't add plugin '%s' to list; reached max plugins (%d)", 
				padd->file, i);
		RETURN_ERRNO(NULL, ME_MAXREACHED);
	}

	// if we found the end of the list, advance end marker
	if(i==endlist)
		endlist++;
	iplug = &plist[i];

	// copy filename into this free slot
	STRNCPY(iplug->filename, padd->filename, sizeof(iplug->filename));
	// Copy file offset ptr.
	// Can't just copy ptr, as it points to offset in padd, which will go
	// away; need to point to corresponding offset in iplug.
	iplug->file = iplug->filename + (padd->file - padd->filename);
	// copy description
	STRNCPY(iplug->desc, padd->desc, sizeof(iplug->desc));
	// copy pathname
	STRNCPY(iplug->pathname, padd->pathname, sizeof(iplug->pathname));
	// copy source
	iplug->source=padd->source;
	// copy status
	iplug->status=padd->status;	
	//copy other things
	iplug->source_plugin_index = padd->source_plugin_index;

	return(iplug);
}
예제 #11
0
// Add the given user msg the list and return the instance.
// meta_errno values:
//  - ME_MAXREACHED		reached max number of msgs allowed
MRegMsg * DLLINTERNAL MRegMsgList::add(const char *addname, int addmsgid, int addsize) {
	MRegMsg *imsg;

	if(endlist==size) {
		// all slots used
		META_ERROR("Couldn't add registered msg '%s' to list; reached max msgs (%d)",
				addname, size);
		RETURN_ERRNO(NULL, ME_MAXREACHED);
	}

	imsg = &mlist[endlist];
	endlist++;

	// Copy msg data into empty slot.
	// Note: 'addname' assumed to be a constant string allocated in the
	// gamedll.
	imsg->name=addname;
	imsg->msgid=addmsgid;
	imsg->size=addsize;

	return(imsg);
}
예제 #12
0
mBOOL MHook::call(event_args_t *args, const char *logline) {

    MPlugin *plug;

    // missing necessary data

    if(type==H_NONE || !pfnHandle)

        RETURN_ERRNO(mFALSE, ME_BADREQ);

    // no event for event hook

    if(type==H_EVENT && event==EV_NONE)

        RETURN_ERRNO(mFALSE, ME_BADREQ);

    // no match string for logline hook

    if(type!=H_EVENT && !match)

        RETURN_ERRNO(mFALSE, ME_BADREQ);



    if(!(plug=Plugins->find(pl_index))) {

        META_ERROR("Couldn't find plugin index '%d' for hook", pl_index);

        RETURN_ERRNO(mFALSE, ME_NOTFOUND);

    }



    // Skip any paused plugins, for instance...

    if(plug->status!=PL_RUNNING)

        RETURN_ERRNO(mFALSE, ME_SKIPPED);



    switch(type) {

    case H_EVENT:

    {

        event_func_t pfn;

        pfn=(event_func_t) pfnHandle;

        pfn(event, args, logline);

    }

    break;

    case H_TRIGGER:

    case H_STRING:

    case H_REGEX:

    {

        logmatch_func_t pfn;

        pfn=(logmatch_func_t) pfnHandle;

        pfn(match, args, logline);

    }

    break;

    default:

        META_ERROR("Unrecognized hook type (%d) from plugin '%s'",

                   type, plid->name);

        RETURN_ERRNO(mFALSE, ME_ARGUMENT);

        break;

    }

    return(mTRUE);

}
예제 #13
0
int MHookList::add(plid_t plid, hook_t type, const char *match,

                   logmatch_func_t pfnHandle)

{

    int i;



    if(!plid || !match || !pfnHandle)

        RETURN_ERRNO(0, ME_ARGUMENT);

    if(type == H_NONE || type == H_EVENT)

        RETURN_ERRNO(0, ME_BADREQ);



    // any open slots?

    if(endlist==size) {

        plugin_info_t *plinfo;

        plinfo=(plugin_info_t *) plid;

        META_ERROR("Couldn't add log hook '%s' for plugin '%s'; reached max hooks (%d)", match, plinfo->name, size);

        RETURN_ERRNO(0, ME_MAXREACHED);

    }



    // Find either:

    //  - a slot in the list that's not being used (malloc'd)

    //  - the end of the list

    for(i=0; hlist[i]; i++);

    if(i==endlist)

        endlist++;



    MXlock();

    hlist[i] = new MHook(i+1, plid, type, match, pfnHandle);

    MXunlock();



    // malloc failed?

    if(!hlist[i]) {

        plugin_info_t *plinfo;

        plinfo=(plugin_info_t *) plid;

        META_ERROR("Couldn't add game event hook for plugin '%s'; malloc failed: %s", plinfo->name, strerror(errno));

        RETURN_ERRNO(0, ME_NOMEM);

    }



    return(i);

}
예제 #14
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);
}
예제 #15
0
mBOOL MHookList::enqueue(MFuncQueue *mfq, hook_t htype, event_args_t *evargs,

                         const char *logline)

{

    int i;

    META_ERRNO ret=ME_NOERROR;



    if(!mfq || !evargs || !logline)

        RETURN_ERRNO(mFALSE, ME_ARGUMENT);

    if(htype==H_NONE)

        RETURN_ERRNO(mFALSE, ME_BADREQ);



    MXlock();

    for(i=0; i < endlist && hlist[i] && hlist[i]->type==htype; i++) {

        MHook *ihook;

        ihook=hlist[i];

        switch(ihook->type) {

        case H_EVENT:

            if(ihook->event == evargs->evtype)

                ihook->enqueue(mfq, evargs, logline);

            break;

        case H_TRIGGER:

            if(strmatch(ihook->match, evargs->action))

                ihook->enqueue(mfq, evargs, logline);

            break;

        case H_STRING:

            if(strstr(logline, ihook->match))

                ihook->enqueue(mfq, evargs, logline);

            break;

        case H_REGEX:

            META_LOG("Not currently handling REGEX hooks...");

            ret=ME_BADREQ;

            break;

        default:

            META_ERROR("Invalid hook type (%d) encountered", ihook->type);

            ret=ME_BADREQ;

            break;

        }

    }

    MXunlock();

    if(ret==ME_NOERROR)

        return(mTRUE);

    else

        RETURN_ERRNO(mFALSE, ret);

}
예제 #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);
}
예제 #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);
}